/* Bangalore Cravings deck v2 design system.
   Palette reconciled from BRANDING-REFS.md (discipline) + GROUNDING (Karnataka colours, NOT Mughlai
   maroon+gold). See BC-DECK-SPEC-V2.md for the citation table.

   DELIBERATELY ABSENT, so the tells cannot come back (DESIGN-LEAK-REGISTER section D):
     - no .rail        (D1: bottom "section label + NN / 15" marker)
     - no .rule        (D2: the line under every heading)
     - no .card        (D3: box/card grids)
     - no global left band on .slide (D4: the same furniture on every slide)
   Each slide brings its OWN compositional logic. Shared here: colour, type, grain, image treatment. */

@import url("../assets/fonts/bc-type.css");   /* THE LOCKED IDENTITY, self-hosted. Same four faces as the posts. */
/* REMOVED 2026-07-30: an @import of general-sans from api.fontshare.com. It survived the type
   lock, and the spec meanwhile claimed the identity was self-hosted in one file. Nothing in this
   stylesheet or any slide referenced the family, so it fetched a stylesheet on every render and
   used none of it; the shoot reported it as a failed request on slide 27. A deck that has to
   reach the network to render cannot be handed to a client on a laptop in a restaurant. */

:root{
  /* PALETTE REPLACED 2026-07-29. It is now MEASURED off the six printed dish panels
     (assets/art/*.png, extraction in research/art-palette.json) instead of lifted from Pinterest
     palette pages. The previous set was indefensible in front of the client: --brick was "lifted
     verbatim from the Studio Manuals palette page" and --leaf was chosen as "deliberately NOT
     Mughlai maroon", i.e. it rejected the client's own mark, which they had just paid to sticker
     onto the truck.

     What the measurement found: every one of the six panels is struck on the SAME cream stock
     (H35-37 S66-75% L86-87%) in the SAME saffron ochre (H31-35 S64-86% L51-56%). Only the field
     colour moves, one per dish. So paper and ochre are constants of the system and the deep ground
     is the deepest field, the dose oxblood. That is the whole palette, and it is derived rather
     than asserted. */
  /* grounds */
  --sandal:#F5E2C6;      /* paper: the stock every panel is printed on. Measured, all six. */
  --sandal-2:#E9D5B4;    /* paper, one step down */
  --leaf:#420D13;        /* deep ground: the dose field. Deepest of the six. Relates to the mark. */
  --leaf-2:#2B0A0D;      /* deeper */
  --brick:#B34A30;       /* the goli field, measured. LARGE TEXT ONLY: paper on it is 4.21:1. */
  --roast:#1C1714;       /* warm near-black, never #000 */
  /* the one accent + the one metal */
  --kesari:#D99242;      /* the ochre every panel shares. 6.27:1 on --leaf, 6.89:1 on --roast. */
  /* SMALL-TEXT accent, added 2026-07-27. Kesari measures 5.84:1 on roast and 2.54:1 on sandal,
     but only 4.08:1 on the leaf ground, so every sub-18px kesari run on a green slide failed WCAG
     AA (measured off the rendered pixels, not estimated: slide 11 had six failing runs).
     This is the MINIMUM lightening along the same hue and saturation that clears 4.5:1 on leaf
     (predicted 4.96:1 there). Aimed ABOVE 4.5 on purpose: the first pass
     targeted exactly 4.50 and MEASURED 4.44, because the grain overlay shifts the ground the
     type actually sits on. The measurement is the authority, not the calculation. It is the accent, one notch up, used only where the type is
     too small to qualify for the 3:1 large-text threshold. */
  /* --kesari-sm existed because the OLD green ground (#23392B) put small ochre runs at 4.08:1.
     The new deep ground is the dose oxblood, on which the base ochre already measures 6.27:1, so
     the lightened variant is no longer doing any work. Kept identical to --kesari so every existing
     `.g-leaf .lbl` rule keeps resolving, and there is now one accent on dark grounds rather than two.
     NOTE the peacock field (#0D696F) is deliberately NOT a token: ochre on it measures 2.49:1 and
     does not clear 4.5 at any lightness along the hue. Peacock is an image field only, never a
     ground for small type. */
  --kesari-sm:#D99242;
  /* And the mirror of it. --kesari-sm LIGHTENS for dark grounds; on the sandal paper that makes
     contrast WORSE, which is what happened to slide 06's Kannada (3.70:1 -> worse) when the
     dark-ground token was applied to a light-ground run. This is the same hue darkened until it
     clears on paper. Pick by GROUND, never by 'the accent needs fixing'. */
  --kesari-dk:#7C4D19;   /* 5.6 nominal: 4.88 measured only 4.45 once grain was over it */
  /* And the same derivation for the brick/goli red, added 2026-07-29. --brick is a measured FIELD
     colour and works as a ground, but used as TEXT on the paper it measures 4.21:1, which deck.css
     already flags as large-text-only. Slides 05, 13 and 19 were setting small brick type on paper.
     This is the same hue and saturation darkened until it clears with HEADROOM. Aimed at 5.6 nominal,
     not 4.5: the first value measured 5.01 on paper but only 4.40 on the rendered slide, because
     the grain overlay shifts the ground the type actually sits on. Same lesson already recorded
     above for --kesari-sm. The measurement is the authority, not the calculation. */
  --brick-dk:#943D28;
  --brass:#A67C3D;       /* hairlines only */

  /* Mapped onto the four locked jobs so every existing rule inherits the identity without a
     slide-by-slide rewrite. --serif is now the VOICE face and --sans the STRUCTURE face, which is
     also the correct job split: headings and labels are structure, anything spoken is voice. */
  --serif:var(--bc-voice);
  --sans:var(--bc-struct);
  --display:var(--bc-name);
  --kan:var(--bc-script),sans-serif;
}

*{margin:0;padding:0;box-sizing:border-box}
html,body{background:#0d0b09}
body{font-family:var(--sans); color:var(--sandal); -webkit-font-smoothing:antialiased}

.deck{display:flex; flex-direction:column; align-items:center; gap:26px; padding:26px 0}
.slide{position:relative; width:1600px; height:900px; overflow:hidden;
  background:var(--roast); box-shadow:0 30px 90px rgba(0,0,0,.6)}

/* ground variants, chosen per slide */
.g-leaf{background:var(--leaf)}
.g-sandal{background:var(--sandal); color:var(--roast)}
.g-brick{background:var(--brick)}
.g-roast{background:var(--roast)}

/* FIELD GROUNDS, added 2026-07-29. The deck had SEVEN slides on the same near-black and never once
   used a field colour as a ground, which is why it read flat beside the prints. Each field is the
   measured value from its printed panel. The comment on each line is the measured contrast of the
   text colour that class sets, so the pairing cannot drift:
     g-dose   paper 12.76  ochre 6.27
     g-kesari paper 11.44  ochre 5.62
     g-kafi   paper  5.07  ochre 2.49  <- ochre BANNED on this ground, paper only
     g-goli   paper  4.21              <- LARGE TEXT ONLY
     g-idli   roast  6.48              <- dark text
     g-puri   roast  4.42              <- dark text, LARGE ONLY */
.g-dose{background:#420D13}
.g-kesari{background:#29205A}
.g-kafi{background:#0D696F}
.g-goli{background:#B34A30}
.g-idli{background:#E77D84; color:var(--roast)}
.g-puri{background:#7F8340; color:var(--roast)}
.g-kafi .lbl,.g-kafi .num{color:var(--sandal)}   /* ochre fails at 2.49 here */
.g-idli .lbl,.g-puri .lbl{color:#3A2408}


/* film grain: fixed overlay, pointer-events none (perf rule from the taste skills) */
.grain{position:absolute; inset:0; opacity:.05; mix-blend-mode:overlay; pointer-events:none; z-index:9;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>")}

/* ---- type ---------------------------------------------------------------- */
/* Headlines: simple, punchy, spoken. Sentence case. Under ~5 words. */
.h{font-family:var(--display); font-weight:400; line-height:.94; letter-spacing:-.02em; text-wrap:balance}
.h-xl{font-size:132px; line-height:.88; letter-spacing:-.03em}
.h-lg{font-size:96px}
.h-md{font-size:68px}
.h-sm{font-size:44px}
.lede{font-family:var(--serif); font-style:italic; font-weight:400; font-size:29px; line-height:1.36; opacity:.96; text-wrap:pretty}
.body{font-size:20px; line-height:1.62; font-weight:400; opacity:.94; max-width:60ch; text-wrap:pretty}
/* Small tiers carry their hierarchy in weight and tracking, not in being too faint to read.
   MEASURED, not asserted: tools/legibility-gate.mjs crops each run out of the rendered PNG,
   classifies glyph vs ground by distance to the computed colour, and takes the ratio against the
   MEDIAN ground behind it. Floor: 16px absolute, 4.5:1 body, 3.0:1 display. The gate is graded in
   both directions and goes RED on slides 22 and 23.
   The previous note here claimed this scale was "set from the measured floor". It was not: the
   first real run of the gate found 155 failing runs across 17 slides, almost all of them these
   tiers at 13-15px with opacity stacked on top. Opacity dimming is what turned a small size into
   an unreadable one, so hierarchy now comes from weight, tracking and colour. */
.small{font-size:17px; line-height:1.58; opacity:.95}
.tiny{font-size:16px; line-height:1.5; opacity:.95; letter-spacing:.01em}
.num{font-family:var(--serif); font-weight:400; font-variant-numeric:tabular-nums; letter-spacing:-.02em}
/* .kn is what every slide actually writes (13 uses across slides 08, 23 and _menu-card) and it was
   defined NOWHERE, so every Kannada run in this deck has been rendering in a system fallback face
   rather than Noto Sans Kannada. Aliased rather than renamed: the slides are the de facto contract. */
.kan,.kn{font-family:var(--kan)}
.acc{color:var(--kesari)}
.on-sandal{color:var(--roast)}
.on-sandal .body,.on-sandal .small{opacity:.9}

/* ---- imagery ------------------------------------------------------------- */
.img{position:absolute; inset:0; background-size:cover; background-position:center; z-index:1}
.imgbox{background-size:cover; background-position:center}
/* scrims: directional, so the headline always has a dark bed under it */
.scrim-bl{position:absolute; inset:0; z-index:2;
  background:radial-gradient(120% 95% at 12% 92%, rgba(20,14,10,.95) 0%, rgba(20,14,10,.6) 36%, rgba(20,14,10,0) 64%)}
.scrim-b{position:absolute; inset:0; z-index:2;
  background:linear-gradient(180deg, rgba(20,14,10,.32) 0%, rgba(20,14,10,0) 32%, rgba(20,14,10,0) 52%, rgba(20,14,10,.88) 100%)}
.scrim-r{position:absolute; inset:0; z-index:2;
  background:linear-gradient(270deg, rgba(20,14,10,.92) 0%, rgba(20,14,10,.5) 30%, rgba(20,14,10,0) 62%)}
.scrim-t{position:absolute; inset:0; z-index:2;
  background:linear-gradient(180deg, rgba(20,14,10,.7) 0%, rgba(20,14,10,0) 34%)}
/* warm grade so generated + real photography read as one world */
.grade{filter:sepia(.16) saturate(1.04) contrast(1.03) brightness(.97)}
.grade-deep{filter:sepia(.3) saturate(.92) contrast(1.06) brightness(.86)}

/* content layer. Slides set their own padding/flow; this is only the stacking context. */
.pad{position:absolute; inset:0; z-index:4; display:flex; flex-direction:column}

/* ---- small shared atoms (NOT a card) ------------------------------------- */
/* .hair REMOVED. A rule that sits beside a line of text is not a divider, it is a decorative
   dash, and at slide scale it reads as a stray hyphen. Adrian flagged it four rounds running.
   Rules are allowed ONLY between the rows of an actual table or ledger. Use space instead. */
.vhair{width:1px; background:var(--brass); opacity:.35}
.lockup{display:flex; align-items:center; gap:11px}
.lockup .nm{font-family:var(--serif); font-size:17px; font-weight:500; letter-spacing:.01em; opacity:1}
.src{font-size:16px; letter-spacing:.02em; opacity:1; font-variant-numeric:tabular-nums}

/* sentence-case serif micro-label. Replaces the tracked-caps HOW/WHY eyebrow that BOTH VLM critics
   flagged on slides 07, 09, 10, 11 and 14 (register D: no tracked-caps eyebrows/kickers). */
.lbl{font-family:var(--serif); font-size:17px; font-weight:500; color:var(--kesari);
     letter-spacing:0; line-height:1.35}
.lbl-d{font-family:var(--serif); font-size:17px; font-weight:500; color:var(--brick-dk);
       letter-spacing:0; line-height:1.35}

/* Format + status line for the content concepts. Adrian: "you're not showcasing if something is a
   social series or post clearly and it doesn't show", and "they don't do thindi rn" so anything we
   are proposing has to say so. No pill badges (register D). */
.fmt{display:flex; align-items:baseline; gap:10px; font-size:16px; letter-spacing:.01em}
.fmt .f{font-family:var(--serif); font-weight:500; color:var(--kesari); font-size:17px}
.fmt .sep{opacity:.55}
.fmt .c{opacity:.88}
.fmt-d .f{color:var(--brick-dk)}
.fmt-d{color:var(--roast)}
.newtag{font-family:var(--serif); font-style:italic; font-size:16px; color:var(--kesari); opacity:1}
.newtag-d{font-family:var(--serif); font-style:italic; font-size:16px; color:var(--brick-dk)}

/* Legibility, 2026-07-27: small kesari runs on the leaf ground only. Measured fix, see --kesari-sm. */
.g-leaf .lbl, .g-leaf .fmt .f, .g-leaf .newtag{color:var(--kesari-sm)}
.g-sandal .lbl, .g-sandal .fmt .f, .g-sandal .newtag{color:var(--kesari-dk)}
.g-leaf .newtag{opacity:1}

/* ---- Bengaluru object stickers -------------------------------------------- */
/* George's two Pinterest sheets (refs/george/) were the original order and went unused for seven
   rounds. Adrian settled it 2026-07-29: rebuild them as Bengaluru objects rather than borrow the
   pixels, because almost every element on his sheets is another company's trademark, AND treat them
   as DECK DECORATION, not as client assets: "we are not using those stickers to tell them its their
   social assets, its edeck decoration".
   So they sit in margins and never inside a frame that would read as the client's own system.
   Set: assets/stickers/objcut/ — matted with rembg + hole-fill, checked on saturated grounds
   (the enamel sign's white letters were being punched straight through the matte, invisible on
   white). No generated non-Latin script on any of them. */
.stk{position:absolute; z-index:6; pointer-events:none;
     filter:drop-shadow(0 6px 14px rgba(40,20,10,.22))}
