/* The token layer, ported from lib/widgets/liquid/liquid_colors.dart.
 *
 * VALUES ARE COPIED, NOT REINTERPRETED, AND THERE ARE NO EXCEPTIONS ANY MORE.
 * Every hex below is lib/theme/palette.dart, which liquid_colors.dart and
 * lib/utils/colors.dart both read now. When a value changes there it changes
 * here.
 *
 * ── THE PAGE IS THE APP'S AGAIN (2026-09-21) ──────────────────────────────
 *
 * From 2026-09-06 the light page was a cool grey #F0F2F5 under white cards,
 * text was slate, links were iOS blue and buttons were #33C47A: "a document,
 * not a phone screen". The app has since moved to its own palette — a linen
 * page (oat until 2026-09-28), white cards, warm inks, an emerald brand — and
 * the web looking like a
 * different product was the complaint. So every value is Palette's:
 *
 *	--liquid-grouped-background   Palette.page        #F4F1EB / #13110F
 *	--liquid-grouped-surface      Palette.card        #FFFFFF / #26231F
 *	--liquid-chrome-scrim         liquidChromeScrim   page lifted toward white
 *	--liquid-primary-label        Palette.ink         #1F1B16 / #F4EFE8
 *	--liquid-secondary-label      Palette.ink2        #6B6259 / #B3A99D
 *	--liquid-tertiary-label       Palette.ink3        #8A8074
 *	--liquid-separator            Palette.divider     #E4DED3 / #3A352F
 *	--liquid-content-border       Palette.cardBorder  ink at 10% / 14%
 *	--liquid-fill-quiet           Palette.well        #786C5E at 12% / 24%
 *	--liquid-accent               Palette.brand       #047857 / #34D399
 *	--liquid-primary-action       Palette.brandMid    #0C8863, both themes
 *	--liquid-destructive          Palette.urgentMid   #D44254
 *
 * THE PAGE STILL SEPARATES A WHITE CARD, which was the whole reason for the
 * grey. Linen #F4F1EB is closer to white than oat was (1.13:1 against 1.25:1),
 * so --liquid-content-border now carries more of the edge — as it does in the
 * app, which draws it on every card.
 *
 * --liquid-fill-quiet IS AN ALPHA FILL NOW, Palette.well. An opaque grey is
 * right on only one surface; a hover on a white card, a chip on the page
 * and a selected row in the dark all need "one step off whatever is under
 * it", which is what an alpha of the warm neutral gives in both themes.
 *
 * ── THERE IS NO GLASS LAYER ON THE WEB (removed 2026-09-06) ───────────────
 *
 * This sheet used to carry a data-glass="on" branch: translucent content
 * surfaces plus a blur/saturate backdrop-filter, mirroring the app's
 * glassmorphism flag, with a prefers-reduced-transparency block folding it back
 * off the way iOS Reduce Transparency does.
 *
 * IT NEVER RENDERED ONCE. Nothing in this service ever set data-glass on
 * <html> — not layout.html, not layout-public.html, not any handler — so the
 * attribute selector matched no element on any page ever served, and the
 * reduced-transparency block only reset values to what they already were. About
 * thirty backdrop-filter declarations in app.css read a token that was
 * permanently `none`.
 *
 * So it is gone by request, and "only dark and light" is now literally what the
 * sheet implements. --liquid-backdrop is deleted rather than pinned to none: a
 * token every surface reads and no surface can change is a cost with no
 * benefit, and its presence invited the next person to wire the flag up.
 *
 * --liquid-content-surface SURVIVES and is now always --liquid-grouped-surface.
 * That is deliberate, not an oversight: it is the ROLE ("the fill a content
 * surface takes") against a VALUE, and roughly thirty rules read it. If a
 * translucency layer is ever wanted again this is the one line it changes.
 */

:root {
  /* Palette.page — the linen page behind every grouped list. */
  --liquid-grouped-background: #F4F1EB;
  /* What content dissolves into under floating chrome. Never transparent:
   * a zero-alpha scrim skips the dissolve entirely and leaves faint blur
   * bands with rows sliding under the title still fully legible. */
  --liquid-chrome-scrim: #F7F5F1;
  /* The rows themselves — lighter than the page in both themes, because
   * content sits ABOVE its background rather than being carved into it. */
  --liquid-grouped-surface: #FFFFFF;
  /* Flat chrome has its own brighter token. Flat mode is flat: there is no
   * bevel to fall back on, so the fill is what separates chrome from page. */
  --liquid-flat-chrome-fill: #FFFFFF;

  /* THE QUIET FILL — a hover, a selected row, a recessed track. Palette.well:
   * an alpha of the warm neutral, so it is one step off whatever it sits on
   * (a white card, the page, a dark card) without a value per surface. */
  --liquid-fill-quiet: rgba(120, 108, 94, 0.12);

  --liquid-separator: #E4DED3;
  --liquid-secondary-label: #6B6259;
  --liquid-tertiary-label: #8A8074;
  --liquid-primary-label: #1F1B16;
  /* Palette.inset — a field or a recessed panel inside a white card. */
  --liquid-inset: #F1EDE6;
  /* Palette.track — the recessed track of a segmented control and the phone
   * bar, holding a white thumb. Not --liquid-inset: that sits 1.03:1 on the
   * linen page and the track lost its edge (the app moved on 2026-09-28). */
  --liquid-track: #E6E1D8;
  /* The domain accent for pings, Palette.pingLight. */
  --liquid-ping-accent: #2D4F9E;
  /* Palette.onFill over the ping accent: white on the deep blue, ink on the
   * light one (the send square's glyph). */
  --liquid-on-ping-accent: #FFFFFF;
  /* A selected chooser: Palette.brandSelectedFill + brandSelectedInk. */
  --liquid-selected-fill: #D8EFE4;
  --liquid-selected-ink: #065F46;

  /* THE HAIRLINE A CONTENT SURFACE IS OUTLINED WITH — liquidContentBorder in
   * lib/widgets/liquid/liquid_colors.dart, copied like every other value here.
   *
   * IT WAS MISSING, AND ITS ABSENCE IS WHY NOTHING ON THIS SITE LOOKED LIKE A
   * CARD. Every LiquidContentSurface in the app draws a fill AND this outline;
   * the web copied the fill only. The fill alone was #F1F5F9 on a #F2F2F7 page
   * — four points of lightness — so a card was distinguishable from the page by
   * almost nothing, and the hover outline was the first time anybody could see
   * where one ended. The app never had that problem because the border was
   * always there.
   *
   * THE FILL NOW CARRIES ITS OWN WEIGHT (white on grey, see the header) AND
   * THIS BORDER STAYS ANYWAY. It is not redundant: it is the only thing
   * defining a card's edge in DARK mode at a glance, it is what a card is
   * outlined with in the app, and in light mode it is what keeps a white card
   * from bleeding into the white nav bar it sits beside. A border that is
   * merely no longer load-bearing is not a border to delete.
   *
   * --liquid-separator is NOT this colour and never was. That one divides rows
   * INSIDE a surface; this one is the surface's own edge, and they are
   * different values in the app for the same reason. */
  --liquid-content-border: rgba(31, 27, 22, 0.10);

  /* The one red in the app: destructive confirm, field error border and the
   * icon on a red row are the same value, so they stay the same value.
   *
   * IT IS ALSO THE UNREAD BADGE, which is not a destructive use and is the
   * same hex — LiquidNavBar's Badge is backgroundColor Color(0xFFFF3B30). See
   * .nav__badge in app.css for why that shares this token rather than getting
   * an alias of its own. */
  --liquid-destructive: #D44254;

  /* Palette.brand — links, focus rings, the text cursor and the selected tab;
   * LiquidColors.primaryAccent, a light/dark pair. */
  --liquid-accent: #047857;

  /* Palette.brandMid — kEmeraldNormal, the fill on every filled button and
   * selected capsule in the app. One const in both themes, as in the app. */
  --liquid-primary-action: #0C8863;

  --liquid-destructive-surface: #F6E8EA;
  --liquid-destructive-label: #A8182E;
  --liquid-destructive-icon: #A8182E;
  --liquid-destructive-rim: rgba(168, 24, 46, 0.2);

  /* Content surfaces are opaque. Always — see the header note on the glass
   * layer that used to make this conditional. */
  --liquid-content-surface: var(--liquid-grouped-surface);

  /* THE DOMAIN ACCENTS. One per act — channels orange, pings blue, circles
   * pink — and the chrome takes none of them. kChannelPrimary in
   * lib/models/channel.dart and --liquid-accent are the same two values the
   * app carries.
   *
   * kChannelPrimary IS Palette.channelMid SINCE 2026-09-17, and this followed
   * on 2026-09-20: #EA580C to #BF5C08 light, #FB923C to Palette.channelDark
   * #FFA24F. The app split its orange into a light/mid/dark trio when the
   * palette landed and took the MID for theme-blind call sites, which is what
   * this token is. The lighter pair this replaced failed contrast as text on a
   * white card, which is most of what this token is used for here.
   *
   * THE TINT TABLE TAKES A DIFFERENT SHADE OF THE SAME ORANGE, and that is not
   * a drift: .card__avatar--t0 is Palette.channelLight #B85400, because slot 0
   * of channelTintsLight is a FILL behind white text rather than text itself.
   * See the note above the table in app.css. */
  --liquid-channel-accent: #BF5C08;

  /* CIRCLES ARE A THIRD DOMAIN, NOT A SHADE OF ONE OF THE OTHER TWO.
   * Palette.circleLight in lib/theme/palette.dart, which the app adopted on
   * 2026-09-17 together with the circles glyph. Before that a circle borrowed
   * whatever accent the surface under it happened to be using, which drew an
   * AUDIENCE as though it were a property of the ping aimed at it — and made
   * the same circle two different colours on two screens.
   *
   * circleTint falls back to this when a circle has no colour of its own, so
   * this value is the one a reader actually sees most of the time. */
  --liquid-circle-accent: #C0267F;

  --liquid-radius-row: 10px;
  --liquid-radius-group: 20px;
  --liquid-radius-overlay: 28px; /* LiquidRadius.overlay: menus, dialogs, sheets */
  /* LiquidRadius.card — 20 for a card AND a grouped panel since 2026-09-21; the
   * app uses one radius for both, and the web follows it. */
  --liquid-radius-card: 20px;
  --liquid-radius-capsule: 999px;
  --liquid-hairline: 0.5px;

  /* ── THE VERTICAL RHYTHM — lib/core/spacing.dart ────────────────────────────
   *
   * A PAGE HAS EXACTLY TWO VERTICAL GAPS, and that is the whole idea rather
   * than a naming convention: --space-section between any two blocks and above
   * every section title, --space-header from a title down to what it titles.
   * The app arrived here after every screen had picked its own number — 12
   * under one search field, 14 between one kind of card and 20 between the
   * next — none wrong alone, and together making the sections look randomly
   * placed, because the eye compares a gap with the gap beside it and never
   * with a number.
   *
   * A BLOCK OWNS THE GAP BELOW ITSELF. Nothing adds a gap above a title, or
   * the two stack and the rhythm is gone at exactly the places it is most
   * visible.
   *
   * THESE ARE DECLARED AHEAD OF THEIR ADOPTION, and that is deliberate. app.css
   * still carries its own literals; converting 4000 lines in one pass would be
   * a change no test on this site can see the result of. Each surface takes
   * them as it is rebuilt, so a page is either wholly on the scale or wholly on
   * its old literals — never half, which is the state that reads as a bug. */
  --space-section: 24px;
  --space-header: 8px;

  /* INSIDE ONE BLOCK. Parts of one thing sit closer than separate things, or
   * the eye stops grouping them: a name and its handle at --space-section read
   * as two sections rather than one identity. */
  --space-tight: 4px;   /* a line and the line qualifying it */
  --space-row: 8px;     /* rows inside one card */
  --space-inner: 12px;  /* groups inside one card, and a card's own title */
  --space-card-padding: 16px;

  /* Between siblings of a kind — cards in a list, stacked buttons. A stack is
   * ONE block, so its members sit closer than --space-section, and the block
   * after the stack gets --space-section again. */
  --space-stack: 12px;

  /* The page's side margin, every scrolling page, timelines included. */
  --space-gutter: 20px;

  /* THE PHOTO STRIP.S HEIGHT — kPingImageStripHeight in
   * lib/widgets/shared/ping_image_gallery.dart. Every tile in a run is this
   * tall and takes the width its own aspect ratio asks for, so this one number
   * is the whole size of a gallery. A token rather than a literal because the
   * clamp that keeps the row a row is calc() against it in three places, and
   * three literals is three chances for a strip to disagree with its own
   * bounds. Narrow screens shorten it — see the .gallery block in app.css. */
  --gallery-h: 220px;

  /* WHAT FLOATING CHROME CASTS. The phone bar is a pill hovering over the
   * timeline — the app's LiquidNavBar — and a pill with no shadow reads as a
   * strip somebody forgot to attach to anything. Values from the bar's own
   * BoxShadow: 9pt blur at 0.10 light / 0.26 dark. */
  --liquid-chrome-shadow: 0 4px 14px rgba(31, 27, 22, 0.10);
}

/* Dark. Palette.pageDark, the warm charcoal the app paints (2026-09-21, was
 * true black under slate rows). Cards are Palette.cardDark, one step up. */
:root:not([data-theme="light"]) {
  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --liquid-grouped-background: #13110F;
    --liquid-chrome-scrim: #242220;
    --liquid-grouped-surface: #26231F;
    --liquid-flat-chrome-fill: #38342E;
    /* An alpha fill: one step off the card or the page, in either theme. */
    --liquid-fill-quiet: rgba(120, 108, 94, 0.24);

    /* The dark half of the brand pair. --liquid-primary-action is deliberately
     * NOT here: kEmeraldNormal is Palette.brandMid, one const in both themes. */
    --liquid-accent: #34D399;
    --liquid-separator: #3A352F;
    --liquid-secondary-label: #B3A99D;
    --liquid-tertiary-label: #8A8074;
    --liquid-inset: #312D28;
    --liquid-track: #312D28;
    --liquid-ping-accent: #7C9CFF;
    --liquid-on-ping-accent: #1F1B16;
    --liquid-selected-fill: #123A2C;
    --liquid-selected-ink: #6EE7B7;
    --liquid-primary-label: #F4EFE8;
    --liquid-content-border: rgba(244, 239, 232, 0.14);
    --liquid-channel-accent: #FFA24F;
    --liquid-circle-accent: #F57CC0;
    --liquid-chrome-shadow: 0 4px 14px rgba(0, 0, 0, 0.26);

    --liquid-destructive-surface: rgba(255, 107, 122, 0.20);
    --liquid-destructive-label: #F4EFE8;
    --liquid-destructive-icon: #FF6B7A;
    --liquid-destructive-rim: rgba(255, 107, 122, 0.3);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --liquid-grouped-background: #13110F;
  --liquid-chrome-scrim: #242220;
  --liquid-grouped-surface: #26231F;
  --liquid-flat-chrome-fill: #38342E;
  /* An alpha fill: one step off the card or the page, in either theme. */
  --liquid-fill-quiet: rgba(120, 108, 94, 0.24);

  /* The dark half of the brand pair — see the note in the media query above. */
  --liquid-accent: #34D399;
  --liquid-separator: #3A352F;
  --liquid-secondary-label: #B3A99D;
  --liquid-tertiary-label: #8A8074;
  --liquid-inset: #312D28;
  --liquid-track: #312D28;
  --liquid-ping-accent: #7C9CFF;
  --liquid-on-ping-accent: #1F1B16;
  --liquid-selected-fill: #123A2C;
  --liquid-selected-ink: #6EE7B7;
  --liquid-primary-label: #F4EFE8;
  --liquid-content-border: rgba(244, 239, 232, 0.14);
  --liquid-channel-accent: #FFA24F;
  --liquid-circle-accent: #F57CC0;
  --liquid-chrome-shadow: 0 4px 14px rgba(0, 0, 0, 0.26);

  --liquid-destructive-surface: rgba(255, 107, 122, 0.20);
  --liquid-destructive-label: #F4EFE8;
  --liquid-destructive-icon: #FF6B7A;
  --liquid-destructive-rim: rgba(255, 107, 122, 0.3);
}
