/* ══════════════════════════════════════════════════════════════════════════
   DreamSlip Design Tokens — the single source of colour for the whole product
   ══════════════════════════════════════════════════════════════════════════

   One document links this file today: index.html, the landing page. The app
   is Flutter and cannot read CSS, so its half of the palette is written out
   again in app/lib/core/theme/app_colors.dart — the two are kept in step by
   hand, and a value changed here and not there is a landing page that no
   longer matches the product it opens into.

   The four prototype pages this header used to list — prototype.html,
   web.html, landing.html and components/base.css — have not existed for some
   time, and neither has the screens/ set they belonged to.

   The file is in two layers, and the order matters:

     Layer 1 — the DreamSlip scale. Raw, named by what they are. This is the
               palette; nothing outside this file may invent a value.
     Layer 2 — roles. Named by what they are for, written in terms of layer 1.
               Components reference these, never layer 1 directly, so a
               palette change is one edit here and not a thousand in the pages.

   Colour rules the roles encode, so they do not have to be remembered:
     · There is one accent, --accent, and it is the blue measured out of
       brand/logo/. It marks what can be pressed and nothing else.
     · Hierarchy comes from the four surfaces and the four text steps, not
       from more hues. If a thing needs to stand out, it goes on a higher
       surface or in a heavier weight.
     · Status colours mean what they say and are never restyled to match.
     · No glow. A shadow says a surface is raised; a bloom says it is
       emitting light, and nothing in a community is emitting light.

   **This half and the app's have deliberately come apart (DREAM-475).**
   The palette here is the neutral one; `app/lib/core/theme/app_colors.dart`
   is still the violet set, and the app is still drawn in it. Bringing the
   two back together is the rest of the ticket, and until that lands a
   colour changed here does not reach the product.

   8pt grid · WCAG AA contrast */

:root {

  /* ═══ LAYER 1 · THE DREAMSLIP SCALE ═══════════════════════════════════ */

  /* Backgrounds — the page, and the chrome that frames it.
     Neutral, and that is the point of DREAM-475: what stood here was
     #0D0913 and #0B0810, a violet so dark it reads as black until there is
     a grey beside it, at which point the whole page looks tinted. These are
     the same two steps with the hue taken out. */
  --ds-bg-page:    #0E0E21;
  --ds-bg-sidebar: #0A0A1B;

  /* Surfaces — four steps of elevation. Hierarchy is built from these
     four and nothing else; a fifth hue is how a dark UI starts to look busy. */
  --ds-surface-primary:   #15152D;  /* cards, panels */
  --ds-surface-secondary: #191938;  /* nested surfaces, inputs */
  --ds-surface-hover:     #1E1E45;  /* pointer is over it */
  --ds-surface-selected:  #22224F;  /* it is the current one */

  /* Borders — three weights, and all three are structure rather than
     decoration. They were #2D1B39, #4B1768 and #6B2990: a violet edge bright
     enough to be the loudest thing on a quiet card. A border says where a
     surface ends and nothing else. */
  --ds-border-subtle:  #26282D;
  --ds-border-default: #33363C;
  --ds-border-hover:   #41639B;

  /* Text — four steps, cool, because the surfaces above them are. These were
     neutral greys, which was right while the ground was neutral charcoal and
     stopped being right when it went cool: a grey ink on a blue-black page
     reads dead beside anything that carries the tint. Green sits level with
     red or just above it and never below, which is the line between this and
     the violet that was removed. It was a cool grey at 28% saturation and
     measured as cool while reading as grey, said so twice with a colour
     picker; it is a sky blue at 45% now, hue 206. Readability never
     constrained the choice — the contrast on a card moves by a fifth of a
     point across the whole range — so what limited it was leaving the
     signal blue room to still be rare. The same four values are in
     app_colors.dart and the two have to move together. */
  --ds-text-primary:   #F0F5F9;
  --ds-text-secondary: #AAC8DF;
  --ds-text-muted:     #6FA2C8;
  --ds-text-disabled:  #326185;

  /* The one accent, and it is the blue out of the mark.
     The circle's right half runs from #011747 to #0337AB, which is too dark
     to carry on this background. The purple and the pink it replaces were in
     no DreamSlip asset anywhere, which is the whole argument: this one is
     measurable, out of brand/logo/.

     **How far to lighten it is decided by white, not by eye.** The obvious
     answer is #4D8DFF, which is a fine ink on the page at 5.96:1 — and it
     shipped here for an afternoon before anybody put white on it, where it
     gives **3.20:1** and fails AA on the one control this page has. One hue
     cannot do both: white on it wants a luminance under 0.183 and reading
     it on the page wants over 0.197. The fill wins, because the label on it
     is text and the accent elsewhere is icons and 13px labels at 3:1.

     So this is the lightening where white clears 4.5 — 4.59:1, the same
     margin the violet it replaces had at 4.51 — and it reads on the page at
     4.15:1. `app/lib/core/theme/app_colors.dart` carries the same value and
     `app_colors_test.dart` is where the arithmetic lives. */
  --ds-blue:       #3671DE;
  --ds-blue-hover: #4E85E8;
  --ds-blue-soft:  #16233A;

  /* Semantic — these mean something, so they are never restyled to match */
  --ds-success: #42B883;
  --ds-warning: #E6A84A;
  --ds-error:   #E2556F;
  --ds-info:    #579DDB;

  /* Translucent forms of the scale. Kept here rather than written inline so
     the alpha values stay consistent between pages. */
  --ds-blue-a12:     rgba( 54, 113, 222, 0.12);
  --ds-blue-a20:     rgba( 54, 113, 222, 0.20);
  --ds-info-a14:     rgba( 87, 157, 219, 0.14);
  --ds-success-a16:  rgba( 66, 184, 131, 0.16);
  --ds-error-a16:    rgba(226,  85, 111, 0.16);
  --ds-shadow:       rgba(  0,   0,   0, 0.55);

  /* Neutral overlays. Frosted bars and hover washes need a colour that sits
     on top of whatever is behind them, which a solid surface cannot do. These
     are the only whites in the system and they never carry text. */
  --ds-white-a04:    rgba(255, 255, 255, 0.04);
  --ds-white-a06:    rgba(255, 255, 255, 0.06);
  --ds-white-a08:    rgba(255, 255, 255, 0.08);
  --ds-white-a12:    rgba(255, 255, 255, 0.12);
  --ds-white-a16:    rgba(255, 255, 255, 0.16);
  --ds-white-a22:    rgba(255, 255, 255, 0.22);
  --ds-white-a85:    rgba(255, 255, 255, 0.85);   /* a count inside a filled control */

  /* Translucent forms of the four surfaces, for anything with a blur behind it. */
  --ds-glass-page:   rgba( 14,  14,  33, 0.97);
  --ds-glass-bar:    rgba( 14,  14,  33, 0.72);   /* top bar, page still visible under it */
  --ds-glass-1:      rgba( 21,  21,  45, 0.96);
  --ds-glass-2:      rgba( 25,  25,  56, 0.94);
  /* A control sitting on artwork rather than on a surface: dark enough to hold
     white text over any image, light enough that the image reads through. */
  --ds-glass-dark:   rgba(  0,   0,   0, 0.50);
  --ds-glass-dark-h: rgba(  0,   0,   0, 0.80);
  --ds-scrim:        rgba(  0,   0,   0, 0.70);   /* behind a modal */

  --ds-shadow-soft:  rgba(  0,   0,   0, 0.35);
  --ds-shadow-strong:rgba(  0,   0,   0, 0.70);


  /* ═══ LAYER 2 · ROLES ═════════════════════════════════════════════════
     What the components actually reference. The short names are the
     vocabulary the pages were already written in; they now resolve to the
     scale above, which is what makes one edit re-theme every screen. */

  /* ── Surfaces ── */
  --bg:       var(--ds-bg-page);
  --bg-chrome: var(--ds-bg-sidebar);   /* rail, top bar, bottom nav */
  --s1:       var(--ds-surface-primary);
  --s2:       var(--ds-surface-secondary);
  --s3:       var(--ds-surface-selected);
  --hover:    var(--ds-surface-hover);
  --selected: var(--ds-surface-selected);

  /* ── Borders ── */
  --b1: var(--ds-border-subtle);
  --b2: var(--ds-border-default);
  --b3: var(--ds-border-hover);

  /* ── Text ── */
  --t1: var(--ds-text-primary);
  --t2: var(--ds-text-secondary);
  --t3: var(--ds-text-muted);
  --t4: var(--ds-text-disabled);
  --on-accent: #FFFFFF;

  /* ── The product accent ──
     One interactive colour, named for what it is. It was `--violet`, with
     `--rose` and `--lav` beside it as a second and third accent, and the
     three were handed out by `nth-child` so a row of four cards cycled
     through them. That is decoration standing in for meaning: nothing was
     pink *because* it was pink. There is one accent now and it marks the
     thing you can press. */
  --accent:       var(--ds-blue);
  --accent-hover: var(--ds-blue-hover);
  --accent-s:     var(--ds-blue-soft);

  /* ── Status. Online dots are --ok, not --info: green means present. ── */
  --ok:     var(--ds-success);
  --warn:   var(--ds-warning);
  --err:    var(--ds-error);
  --info:   var(--ds-info);
  --ok-s:   var(--ds-success-a16);
  --err-s:  var(--ds-error-a16);
  --info-s: var(--ds-info-a14);

  /* ── Primary interactive fill ──
     Flat. There was a `--grad` here, blue into purple into pink, for the
     logo and one major call to action; the logo is a supplied file and does
     not need a gradient defined for it, and a call to action in three hues
     is the loudest object on a page whose job is to be read. */
  --primary:        var(--ds-blue);
  --primary-hover:  var(--ds-blue-hover);
  --primary-border: var(--ds-blue);
  --primary-ring:   0 0 0 1px var(--ds-blue-a20);

  /* ── Avatars ──
     Identity, not chrome: members stay individually recognisable. Six steps
     around the accent and through the neutrals rather than six hues, so a
     roster reads as one set of people and not as a paint chart. */
  --av-1: linear-gradient(135deg, #2F4F8F, #3671DE);
  --av-2: linear-gradient(135deg, #22436F, #3C6FC9);
  --av-3: linear-gradient(135deg, #2B4A5C, #4F93A8);
  --av-4: linear-gradient(135deg, #3A3F4A, #6B7483);
  --av-5: linear-gradient(135deg, #1E3A5F, #3671DE);
  --av-6: linear-gradient(135deg, #343A45, #55606F);

  /* ── Artwork placeholders ──
     The dark fills that stand in for a podcast cover, a post image, a reel or
     a group avatar. They are compositions of the surface scale, not new
     colours: the point is that empty artwork recedes into the page instead of
     competing with it. */
  --art-neutral: linear-gradient(145deg, var(--ds-surface-selected),
                                         var(--ds-surface-secondary));
  --art-cool:    linear-gradient(145deg, var(--ds-blue-soft),
                                         var(--ds-surface-selected));
  --art-hero:    linear-gradient(135deg, var(--ds-surface-selected) 0%,
                                         var(--ds-surface-primary) 60%,
                                         var(--ds-bg-page) 100%);
  --art-reel:    linear-gradient(160deg, var(--ds-blue-soft) 0%,
                                         var(--ds-surface-selected) 55%,
                                         var(--ds-surface-secondary) 100%);
  --av-group:    linear-gradient(135deg, var(--ds-surface-selected),
                                         var(--ds-surface-secondary));

  /* ── Card treatment ──
     A surface, a 1px edge and nothing behind it. `--card-glow` was a 30px
     violet bloom under every card; a shadow says a thing is raised, a glow
     says it is emitting, and a list of articles is not emitting. */
  --card-r:      16px;
  --card-border: var(--ds-border-subtle);

  /* ── The resting treatment for pills, chips and secondary buttons ── */
  --rest-bg:     var(--ds-surface-secondary);
  --rest-border: var(--ds-border-subtle);

  /* ── 8pt spacing grid ── */
  --sp-4:  4px;
  --sp-8:  8px;
  --sp-12: 12px;
  --sp-16: 16px;
  --sp-20: 20px;
  --sp-24: 24px;
  --sp-32: 32px;
  --sp-40: 40px;
  --sp-48: 48px;
  --sp-56: 56px;

  /* ── Radius ── */
  --r-4:  4px;
  --r-8:  8px;
  --r-12: 12px;
  --r-16: 16px;
  --r-20: 20px;
  --r-24: 24px;
  --r-full: 9999px;

  /* ── Type scale ── */
  --type-10: 10px;   /* micro label (uppercase only) */
  --type-11: 11px;   /* caption */
  --type-13: 13px;   /* label, meta */
  --type-15: 15px;   /* body */
  --type-17: 17px;   /* subheading */
  --type-22: 22px;   /* title */
  --type-28: 28px;   /* display */

  /* ── Font ──
     One family for everything, at four weights. There is no --font-display
     and there is deliberately no second face: hierarchy here is weight,
     size and position, which is what a grotesque with a real weight axis is
     for. The mark already carries the brand's one piece of lettering, the
     script Slip inside the circle, and a display serif beside it was a
     second voice competing with it.

     Inter rather than a warmer choice because of who reads this: the app
     translates into fifteen languages (translation_language.dart), so the
     face has to cover Latin, Cyrillic and Greek without falling back
     mid-sentence. The app names the same family through the google_fonts
     package in app_theme.dart, and the two have to agree. */
  --font:      'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'SF Mono', 'Fira Mono', ui-monospace, monospace;

  /* ── Touch target minimum ── */
  --tap: 44px;

  /* ── Safe areas (iPhone 14) ── */
  --safe-top: 54px;     /* dynamic island + padding */
  --safe-bottom: 34px;  /* home indicator */
}
