/* ------------------------------------ */
/* Brand tokens                         */
/* ------------------------------------ */

/* The one typeface for the interface. Google Sans Flex is a variable font, so
   every weight below comes from a single file; the license ships beside it
   (GoogleSansFlex-OFL.txt). Recipe names are the exception and keep the
   editorial serif — see --font-recipe.

   The browser is served the woff2: a Latin subset of the variable font, built
   by tools/build_web_fonts.py, which is ~150 KB against the 3.8 MB TTF. The TTF
   stays in the folder and is listed second because Pillow draws the recipe
   cards from it, and because a browser too old for woff2 still gets a face. */
@font-face {
    font-family: "Google Sans Flex";
    src: url("../fonts/GoogleSansFlex-Variable.woff2") format("woff2"),
         url("../fonts/GoogleSansFlex-Variable.ttf") format("truetype-variations");
    font-weight: 100 1000;
    font-display: swap;
}

/* Still used by the generated recipe cards and the graph labels, which are
   drawn by Pillow rather than by the browser, so only the TTF is ever read. */
@font-face {
    font-family: "Archivo";
    src: url("../fonts/Archivo-VariableFont_wdth,wght.ttf") format("truetype-variations");
    font-weight: 100 900;
    font-display: swap;
}

@font-face {
    font-family: "Instrument Serif";
    src: url("../fonts/InstrumentSerif-Regular.woff2") format("woff2"),
         url("../fonts/InstrumentSerif-Regular.ttf") format("truetype");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

:root {
    /* Interface type: Google Sans Flex first, then whatever the OS has. */
    --font-ui: "Google Sans Flex", "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    /* Recipe names stay editorial: the serif is what makes a card read as a card. */
    --font-recipe: "Instrument Serif", Georgia, serif;

    /* ── Type ramp ─────────────────────────────────────────────────────────
       Sizes are named by role rather than by number so a screen asks for "the
       small label" instead of inventing 0.66rem: 11px is the floor for a
       count, 14px is the interface default, 34px is a recipe name on a card.
       Nothing is set below 11px, and nothing in the chrome is set above 18px
       except editorial type. */
    --text-2xs: 0.6875rem; /* 11px — counts, micro labels */
    --text-xs: 0.75rem;    /* 12px — captions, meta */
    --text-sm: 0.8125rem;  /* 13px — secondary UI */
    --text-base: 0.875rem; /* 14px — the interface default */
    --text-md: 1rem;       /* 16px — inputs, body copy */
    --text-lg: 1.125rem;   /* 18px — sheet titles */
    --text-xl: 1.375rem;   /* 22px — page titles */
    --text-2xl: 1.75rem;   /* 28px */
    --text-3xl: 2.125rem;  /* 34px — recipe names on a card */

    --leading-none: 1;
    --leading-tight: 1.15;
    --leading-snug: 1.35;
    --leading-normal: 1.5;
    --leading-relaxed: 1.65;

    --weight-regular: 400;
    --weight-medium: 500;
    --weight-semibold: 600;
    --weight-bold: 700;

    /* Uppercase micro labels open up; display type closes. */
    --tracking-tight: -0.01em;
    --tracking-normal: 0;
    --tracking-wide: 0.06em;
    --tracking-wider: 0.12em;

    /* ── Space ─────────────────────────────────────────────────────────────
       One 16px rhythm with a single 8px half step, for things that read as
       one unit (a chip's glyph and its label). Every gap, padding and margin
       in the chrome is a step on this scale rather than a one-off rem value. */
    --space-half: 8px;
    --space-1: 16px;
    --space-2: 32px;
    --space-3: 48px;
    --space-4: 64px;
    --space-5: 96px;

    /* ── Shape ─────────────────────────────────────────────────────────── */
    --radius-sm: 10px;
    --radius-md: 14px;
    --radius-lg: 20px;
    --radius-xl: 26px;
    --radius-pill: 999px;

    /* ── Motion ────────────────────────────────────────────────────────────
       Short and out-eased: things arrive, they do not perform. */
    --duration-fast: 140ms;
    --duration-base: 200ms;
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-standard: cubic-bezier(0.2, 0.7, 0.3, 1);

    /* Editorial theme (black surfaces, orange accent) */
    --ui-bg: #0b0b0d;
    --ui-surface: #141417;
    --ui-line: rgba(245, 242, 234, 0.10);
    --ui-text: #f5f2ea;
    --ui-muted: #9a958c;
    --ui-accent: #ff6a1a;

    /* Accent. Orange on black is the theme; on a light page the same orange
       is too pale for text, so accent-ink is the readable one for type and
       on-accent is what sits on top of an orange fill. */
    --color-accent: #ff6a1a;
    --color-accent-dark: #e2560f;
    --color-accent-light: #ffe0cc;
    --color-accent-ink: #c2410c;
    --color-on-accent: #14110b;

    /* Backgrounds */
    --color-bg-nav: #111827;
    --color-bg-page: #ffffff;
    --color-bg-surface: #f1f5f9;
    --color-bg-dark: #111827;

    /* Text */
    --color-text-primary: #111827;
    --color-text-muted: #94a3b8;
    --color-text-light: #ffffff;

    /* Borders */
    --color-border: #e2e8f0;
}

/* ------------------------------------ */
/* Cross-cutting behaviour              */
/* ------------------------------------ */

/* One focus ring, everywhere. `:where()` keeps the specificity at zero so a
   component can still draw its own without a selector war, and the offset
   colour is the page behind the control rather than a hard-coded black. */
:where(a, button, [role="button"], summary, input, select, textarea):focus-visible {
    outline: 2px solid var(--ui-accent);
    outline-offset: 2px;
}

/* The interface is mostly transitions on hover and on arrival. Someone who
   asked their system for less motion gets none of it, not a shorter version. */
@media (prefers-reduced-motion: reduce) {
    :where(*, *::before, *::after) {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ------------------------------------ */
/* Button component                     */
/* ------------------------------------ */

.button--primary {
    background: var(--color-accent);
    color: var(--color-on-accent);
    border: none;
    border-radius: 6px;
    padding: 8px 16px;
    font-weight: 600;
    cursor: pointer;
}

.button--primary:hover {
    background: var(--color-accent-dark);
}

/* ------------------------------------ */
/* Segmented toggle component           */
/* ------------------------------------ */

/* Equal halves sharing a sunken track, for picking between two labelled
   alternatives. Use .toggle-switch instead when a single option is simply
   being turned on or off. */

.segmented-toggle {
    display: flex;
    flex-direction: row;
    gap: 2px;
    padding: 3px;
    border-radius: 8px;
    background: #e1e7ed;
}

.segmented-toggle__option {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px;
    border: none;
    border-radius: 6px;
    font-family: inherit;
    font-size: .78rem;
    font-weight: 500;
    text-align: center;
    text-decoration: none;
    color: #6b7684;
    background: transparent;
    cursor: default;
}

/* Only a half that navigates or acts is interactive. The half representing the
   current state renders without href / with disabled, so it keeps the default
   cursor and no hover. */

.segmented-toggle__option[href],
.segmented-toggle__option:not(:disabled) {
    cursor: pointer;
}

.segmented-toggle__option[href]:hover,
.segmented-toggle__option:not(:disabled):hover {
    color: var(--color-text-primary);
}

.segmented-toggle__option--active {
    font-weight: 600;
    color: var(--color-on-accent);
    background: var(--color-accent);
    box-shadow: 0 2px 8px rgba(255, 106, 26, .28);
}

.segmented-toggle__option--active:hover {
    color: var(--color-on-accent);
}

/* ------------------------------------ */
/* Toggle switch component              */
/* ------------------------------------ */

/* An on/off switch for a single named option, as opposed to .segmented-toggle
   which picks between two labelled alternatives. Slightly larger than the
   gallery's "Sort by rating" switch, which predates this component and still
   carries its own copy of these rules. */

.toggle-switch {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .85rem;
    color: #555555;
    cursor: pointer;
    user-select: none;
}

.toggle-switch input[type="checkbox"] {
    position: relative;
    flex-shrink: 0;
    width: 2.4rem;
    height: 1.35rem;
    border-radius: 1rem;
    appearance: none;
    background: #cccccc;
    cursor: pointer;
    transition: background .2s;
}

.toggle-switch input[type="checkbox"]:checked {
    background: var(--color-accent);
}

.toggle-switch input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.toggle-switch input[type="checkbox"]::after {
    content: '';
    position: absolute;
    top: .15rem;
    left: .15rem;
    width: 1.05rem;
    height: 1.05rem;
    border-radius: 50%;
    background: #ffffff;
    transition: left .2s;
}

.toggle-switch input[type="checkbox"]:checked::after {
    left: calc(100% - 1.2rem);
}

/* Subtle variant, for switches that filter a view rather than navigate between
   sections. The active half lifts off a lighter track instead of taking the
   accent colour, so it does not compete with the primary toggle above it. */

.segmented-toggle--subtle {
    gap: 0;
    padding: 3px;
    border-radius: 8px;
    background: #f1f4f7;
}

.segmented-toggle--subtle .segmented-toggle__option {
    padding: 5px;
    border-radius: 6px;
    font-size: 11.5px;
    font-weight: 500;
    color: #8a93a3;
}

.segmented-toggle--subtle .segmented-toggle__option--active {
    font-weight: 600;
    color: var(--color-text-primary);
    background: var(--color-bg-page);
    box-shadow: 0 1px 3px rgba(20, 30, 45, .12);
}

.segmented-toggle--subtle .segmented-toggle__option--active:hover {
    color: var(--color-text-primary);
}

/* ------------------------------------ */
/* Favorite star                        */
/* ------------------------------------ */

/* One control at three sizes: the badge on an explorer card, the chip in the
   quick-look panel and the header button on a recipe page. Lives here because
   the same partial renders on three pages. The badge sits on a photo, so it
   carries its own glass backing; the page header is light, and overrides the
   colours below. */

.fav-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, .18);
    border-radius: 999px;
    background: rgba(12, 12, 14, .42);
    color: rgba(255, 255, 255, .92);
    font-family: var(--font-ui, sans-serif);
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .08em;
    line-height: 1;
    text-transform: uppercase;
    cursor: pointer;
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    transition: color .15s ease, background .15s ease, border-color .15s ease;
}

.fav-btn svg {
    width: 1.05em;
    height: 1.05em;
    flex-shrink: 0;
}

.fav-btn:hover {
    border-color: rgba(255, 106, 26, .75);
    color: var(--ui-accent);
}

.fav-btn:focus-visible {
    outline: 2px solid var(--ui-accent);
    outline-offset: 2px;
}

.fav-btn--on {
    background: var(--ui-accent);
    border-color: var(--ui-accent);
    color: #14110b;
}

.fav-btn--on:hover {
    background: #ff8a4d;
    border-color: #ff8a4d;
    color: #14110b;
}

/* Card badge: in the corner of the photo, above the card's hit area. */

.fav-btn--card {
    position: absolute;
    top: .7rem;
    left: .7rem;
    z-index: 4;
    width: 30px;
    height: 30px;
    font-size: .9rem;
}

/* Panel chip: sized to sit in the quick-look dialog's tag row. */

.fav-btn--panel {
    padding: .34rem .62rem .34rem .5rem;
    font-size: .58rem;
    letter-spacing: .1em;
}

/* Page header: a sibling of the close button, on the light detail surface. */

.fav-btn--page {
    width: 2.5rem;
    height: 2.5rem;
    margin: 0 .5rem 0 .75rem;
    border-radius: 50%;
    border-color: transparent;
    background: rgba(0, 0, 0, .07);
    color: var(--color-text-primary);
    font-size: 1rem;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    flex-shrink: 0;
}

.fav-btn--page:hover {
    border-color: transparent;
    background: rgba(0, 0, 0, .14);
    color: var(--color-accent-dark);
}

/* The page button is a circle in a tight header, so the word would spill out of
   it. It stays in the markup for the accessible name and is hidden from sight;
   the aria-label on the button already says the same thing. */
.fav-btn--page .fav-btn__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    white-space: nowrap;
    clip-path: inset(50%);
}

.fav-btn--page.fav-btn--on,
.fav-btn--page.fav-btn--on:hover {
    background: var(--color-accent);
    color: #14110b;
}

@media (max-width: 900px) {
    .fav-btn--card { top: .5rem; left: .5rem; width: 28px; height: 28px; }
}
