/* ═══════════════════════════════════════════════════════════════════════════
   DIAGRAM / BOX COMPONENT SET — §D4 (B-004 / AC-1.1)

   The §D4 pattern set, generalized from the gold-standard deck
   (SecondBrain/.../presentation-v1.html). Every pattern reads the shared
   design tokens (tokens.css → theme.css cascade) so radius / border / accent
   stay consistent across all 16 presets and both themes.

   ── Diagram-scoped tokens ───────────────────────────────────────────────
   These alias the global design tokens to a single diagram vocabulary so the
   nine patterns never hard-code a radius or a border width. Authors who want
   a tighter or looser look swap ONE variable rather than every rule.

   The radius aliases below point into the global 3-step scale (B-031b):
     layer / flow / gain ........ --radius-md (8px)   (--diagram-radius)
     coverage card .............. --radius-sm (4px)   (--diagram-radius-tight)
     comparison frame ........... --radius-lg (16px)  (--diagram-radius-frame)
     card / role-grid card ...... --radius-lg (16px)  (--diagram-radius-card)
     pill / loop-note pill ...... 999px               (--diagram-radius-pill)
   The accent FILL uses the accent token at low alpha; because the accent token
   resolves to the preset hex (e.g. keynote-dark dark = #2997ff = rgb(41,151,255))
   the rendered fill equals the gold rgba(41,151,255,…). The border colour reads
   `--accent` directly, so its hex is identical to the gold accent.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
    --diagram-radius: var(--radius-md);        /* 8px — layer/flow/gain (B-031b: 12→md) */
    --diagram-radius-tight: var(--radius-sm);  /* 4px — coverage card  (B-031b: 11→sm) */
    --diagram-radius-frame: var(--radius-lg);  /* 16px — comparison frame (B-031b: 14→lg) */
    --diagram-radius-card: var(--radius-lg);   /* 16px — card exact    (B-031b: 16→lg) */
    --diagram-radius-pill: 999px;              /* pill stays as-is */
    --diagram-border-width: 1px;
    --diagram-card-bg: var(--bg-secondary);
    /* Accent tint — the highlighted-state fill shared by .hot / .flag / .gain.
       FALLBACK ONLY: the generated theme.css (theme-css.ts) overrides this
       per-preset with an rgba() derived from the preset's own --accent so the
       fill shares the accent's hue (B-004 cross-preset fix). A plain rgba()
       (not color-mix) keeps html2canvas v1.4.1 happy — see tokens.css. This
       literal is the legacy keynote-blue and only applies to decks whose
       theme.css predates the per-preset derivation. */
    --diagram-accent-tint: rgba(41, 151, 255, 0.1);
}

/* B-010: --diagram-card-bg must re-resolve against the dark --bg-secondary on
   themed decks. In :root it resolves against html (light), and since data-theme
   lives on <body>, diagram cards (.layer/.cov-card/.data-table) would render
   light-on-light (invisible) in dark decks without this re-declaration. */
[data-theme="dark"] {
    --diagram-card-bg: var(--bg-secondary);
}

/* ─── 1. LAYER STACK (레이어 스택) ──────────────────────────────────────────
   Stacked horizontal rows (e.g. an L0→L4 capability stack). `.flag` lifts a
   row with an accent border + glow. Gold: .layer / .layer.flag. */
.stack {
    display: flex;
    flex-direction: column;
    gap: 10.8px;
    width: 100%;
    max-width: 840px;
    margin-inline: auto; /* B-116: not `margin: 0 auto` — see the .data-table note */
}
.layer {
    display: flex;
    align-items: center;
    gap: 19.2px;
    background: var(--surface-bg);
    border: var(--diagram-border-width) solid var(--card-border);
    border-radius: var(--diagram-radius);
    box-shadow: var(--surface-shadow);
    transition: var(--surface-transition);
    padding: 15.1px 22.4px;
    /* B-056: shared level-label column width. Each .layer is its own flex row, so
       the .lv column can only align across rows if every row reserves the SAME
       width. Default fits a ~3-CJK-char level tag (앱/서비스/데이터/인프라) on one
       line; a deck whose labels run longer overrides this one token in deck.css
       (B-055) instead of per-slide hacks. */
    --lv-basis: 54.4px;
}
.layer .lv {
    font-weight: 800;
    color: var(--accent-text);
    font-size: 18.4px;
    /* B-056: fixed basis (was `min-width`) so a longer label no longer grows its
       own row's .lv and shoves .nm right — .nm start-x stays aligned down the
       stack (ragged left edge fixed). `min-width: 0` overrides the flex-item
       default (`min-width: auto` = min-content), which would otherwise still let
       a multi-char label balloon the box past the basis. Short labels render
       identically to before; a label wider than the reserved column overflows
       into the gap rather than displacing .nm. If a deck's labels routinely run
       long, widen the column once via `--lv-basis` in deck.css (B-055) instead of
       per-slide hacks. */
    flex: 0 0 var(--lv-basis);
    min-width: 0;
}
.layer .nm {
    font-weight: 700;
    font-size: var(--body-size);
    color: var(--fg);
    flex: 0 0 auto;
    min-width: 168px;
}
.layer .ds {
    font-size: var(--small-size);
    color: var(--muted);
}
.layer.flag {
    border-color: var(--accent);
    box-shadow: 0 0 0 1px var(--accent), 0 0 26px var(--accent-glow);
    background: var(--diagram-accent-tint);
}
.layer.flag .ds { color: var(--fg); }

/* ─── 2. FLOW / CYCLE (플로우·사이클 + loop-note) ──────────────────────────
   A horizontal sequence of steps joined by arrows. `.loop-note` is the
   dashed "cycle repeats" pill the gold deck appends under a cyclic flow. */
.flow-diagram {
    display: flex;
    align-items: stretch;
    justify-content: center;
    gap: 14.4px;
    flex-wrap: wrap;
}
.flow-step {
    background: var(--surface-bg);
    border: var(--diagram-border-width) solid var(--card-border);
    border-radius: var(--diagram-radius);
    box-shadow: var(--surface-shadow);
    transition: var(--surface-transition);
    padding: 15.1px 16px;
    text-align: center;
    width: 150px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.flow-step.hot {
    border-color: var(--accent);
    background: var(--diagram-accent-tint);
    box-shadow: 0 0 20px var(--accent-glow);
}
.flow-number {
    font-size: 21.6px;
    font-weight: 800;
    color: var(--accent-text);
    margin-bottom: 0.15rem;
}
.flow-label {
    font-size: var(--body-size);
    font-weight: 700;
    color: var(--fg);
}
.flow-desc {
    font-size: var(--small-size);
    color: var(--muted);
    margin-top: 0.15rem;
}
.flow-arrow {
    display: flex;
    align-items: center;
    font-size: 24px;
    color: var(--accent-text);
    font-weight: 300;
}
.loop-note {
    margin-top: 21.6px;
    text-align: center;
    font-size: var(--body-size);
    color: var(--accent-text);
    font-weight: 600;
}
.loop-note span {
    display: inline-block;
    border: 1px dashed var(--accent);
    border-radius: var(--diagram-radius-pill);
    padding: 0.3rem 1rem;
}

/* ─── 3. COVERAGE GRID (커버리지 — 3열 카드) ───────────────────────────────
   A dense 3-column card grid that collapses to 2-up then 1-up. Gold: .cov-grid
   / .cov-card. */
.cov-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 15.2px;
    width: 100%;
    max-width: 980px;
    margin-inline: auto; /* B-116: not `margin: 0 auto` — see the .data-table note */
}
.cov-card {
    background: var(--surface-bg);
    border: var(--diagram-border-width) solid var(--card-border);
    border-radius: var(--diagram-radius-tight);
    box-shadow: var(--surface-shadow);
    transition: var(--surface-transition);
    padding: 13px 16px;
}
.cov-card .cc-t {
    font-size: var(--small-size);
    font-weight: 800;
    color: var(--accent-text);
    letter-spacing: 0.02em;
}
.cov-card .cc-i {
    font-size: var(--small-size);
    color: var(--muted);
    margin-top: 0.22rem;
    line-height: 1.42;
}

/* ─── 4. COMPARISON (비교표 — before/after) ────────────────────────────────
   Two-column framed comparison. The 1px grid gap on a card-border background
   draws the divider lines. Gold: .comparison-grid / .comp-*. */
.comparison-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1px;
    background: var(--card-border);
    border-radius: var(--diagram-radius-frame);
    overflow: hidden;
    max-width: 640px;
    margin-inline: auto; /* B-116: not `margin: 0 auto` — see the .data-table note */
    width: 100%;
}
/* B-054: cells are flat, row-interleaved grid items (header L, header R, cell
   L, cell R, …) — the `1fr 1fr` grid pairs each L/R into one implicit row, so a
   taller cell grows the row and its partner stretches to match (tops already
   align). Centering the content in that stretched box makes an uneven pair
   (1-line vs 2-line) read as balanced instead of top-ragged. MUST author the
   markup flat (not as two column wrappers) or the row-pairing is lost — see
   docs/diagram-patterns.md §4. */
.comp-header {
    padding: 14px;
    font-weight: 700;
    font-size: var(--body-size);
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
.comp-before { background: var(--bg-secondary); }
.comp-after {
    background: var(--diagram-accent-tint);
    color: var(--accent-text);
}
.comp-cell {
    padding: 17.3px;
    font-size: var(--body-size);
    background: var(--bg);
    text-align: center;
    color: var(--muted);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
.comp-cell.hot {
    color: var(--accent-text);
    font-weight: 700;
}
/* Back-compat aliases for the pre-B-004 comparison markup (.comp-item). */
.comp-item {
    padding: 12.8px;
    font-size: var(--small-size);
    color: var(--muted);
    background: var(--bg);
}
.comp-item.highlight { color: var(--accent-text); font-weight: 600; }

/* ─── 5. GAIN / CALLOUT STRIP (gain·callout 스트립) ────────────────────────
   An accent-bordered "so-what" strip that sits under a diagram. Gold: .gain. */
.gain,
.callout {
    margin-top: 18.4px;
    background: var(--diagram-accent-tint);
    border: var(--diagram-border-width) solid var(--accent);
    border-radius: var(--diagram-radius);
    padding: 15.1px 20.8px;
}
.gain .g-label,
.callout .g-label {
    font-size: var(--small-size);
    font-weight: 800;
    color: var(--accent-text);
    letter-spacing: 0.03em;
    margin-bottom: 0.25rem;
}
.gain .g-text,
.callout .g-text {
    font-size: var(--body-size);
    color: var(--fg);
    line-height: 1.45;
}
.gain .g-text b,
.callout .g-text b { color: var(--accent-text); font-weight: 700; }

/* ─── 6. BOUNDARY TAG (경계 구분) ───────────────────────────────────────────
   A centered label that marks a boundary between groups of stacked rows.
   `.hot` adds dashed rules above and below. Gold: .boundary-tag. */
.boundary-tag {
    text-align: center;
    font-size: var(--small-size);
    font-weight: 700;
    color: var(--muted);
    letter-spacing: 0.04em;
    padding: 7.6px 0;
}
.boundary-tag.hot {
    color: var(--accent-text);
    border-top: 1px dashed var(--accent);
    border-bottom: 1px dashed var(--accent);
    margin: 5.4px 0;
}

/* ─── 7. DATA TABLE (데이터 테이블) ────────────────────────────────────────
   Borderless rule-separated table with an accent-coloured header row and a
   `.flag` row highlight. Gold: .data-table. */
.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--small-size);
    max-width: 900px;
    /* B-116 (the note the other seven `margin-inline: auto` sites point at): these
       used to be the `margin: 0 auto` SHORTHAND, whose zero block margins out-cascade
       base.css's column-rhythm rule (same 0,1,0 specificity, later source order) — so
       a diagram block followed by a paragraph sat flush, measured 0px on broadsheet
       s6 table → source line while every other pair got --element-gap. The inline
       axis keeps the centring; the block axis belongs to the column. */
    margin-inline: auto;
}
.data-table th,
.data-table td {
    padding: 10.8px 12.8px;
    border-bottom: var(--diagram-border-width) solid var(--card-border);
    text-align: left;
    vertical-align: top;
}
/* B-078: no uppercase register, and the size goes with it. `0.72em` was chosen for
   CAPS — cap-height is ~0.72 of the em, so those headers stood ~0.52em tall. Dropping
   the transform without the size would have left a header quieter than its own body
   row. At the table's own size, x-height lands at ~0.5em: the same optical presence,
   without shouting. Korean headers were penalised twice by the old rule (the transform
   does nothing to Hangul, and Hangul fills the em box, so 0.72em simply made them
   smaller than the data). Weight + accent colour carry the distinction now, matching
   `.card .tag`. */
.data-table th {
    font-weight: 700;
    color: var(--accent-text);
    letter-spacing: 0.06em;
}
.data-table td { color: var(--muted); }
.data-table td b { color: var(--fg); font-weight: 700; }
.data-table tr.flag td { background: var(--diagram-accent-tint); }
.data-table .lv { color: var(--accent-text); font-weight: 800; }

/* ─── 8. PULL QUOTE (pull-quote) ───────────────────────────────────────────
   A large statement line. `.accent` colours the emphasized fragment. Gold:
   .pull. */
.pull {
    font-size: 38.4px;
    font-weight: 800;
    line-height: 1.25;
    letter-spacing: -0.02em;
    max-width: 20ch;
}
.pull .accent { color: var(--accent-text); }

/* ─── 9. ROLE / CRUX GRID (role·crux 그리드) ───────────────────────────────
   3-up card grids. `.role-grid` lists actors; `.crux` lists numbered key
   points with an accent left rule. Both reuse the shared `.card` primitive.
   Gold: .role-grid / .crux. */
.role-grid,
.crux {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 22.4px;
    max-width: 920px;
    margin-inline: auto; /* B-116: not `margin: 0 auto` — see the .data-table note */
    width: 100%;
}
.role-grid .card .tag { display: block; margin-bottom: 0.4rem; }
.crux .card { border-left: 3px solid var(--accent); }
.crux .num {
    font-size: 25.6px;
    font-weight: 800;
    color: var(--accent-text);
}

/* ─── Shared card primitive ────────────────────────────────────────────────
   The base box used by role-grid / crux / general two-up rows. Gold: .card. */
.card {
    background: var(--surface-bg);
    border: var(--diagram-border-width) solid var(--card-border);
    border-radius: var(--diagram-radius-card);
    box-shadow: var(--surface-shadow);
    transition: var(--surface-transition);
    padding: 25.9px;
}
/* B-088: --accent-on-surface, not --accent-text. This label sits on the CARD, and
   --accent-text is derived against the flat page background — a different colour, and
   the difference is about the width of the AA line (4.15-4.36:1 measured across the 16
   presets, floor 4.5). Nothing was wrong with the derivation; it was aimed at the wrong
   ground. Nothing saw it because the deep contrast scan had never been pointed at the
   archetype gallery. */
.card .tag {
    font-size: var(--small-size);
    font-weight: 700;
    color: var(--accent-on-surface);
    letter-spacing: 0.06em;
}
/* B-084: the six-ink category palette had no consumer. `--cat-1`..`--cat-6` and
   their measured `--on-cat-N` counterparts were read by nothing, so a slide whose
   text said "six inks" painted six labels in one accent — the deck asserted a
   palette the page could not show. `data-cat="N"` opts a tag into the chip form
   and picks the Nth ink; without the attribute nothing changes. The text colour
   comes from --on-cat-N, which the generator derives by measuring against that
   specific ink rather than assuming white.

   B-109: this comment used to say those tokens "were emitted by every theme".
   They are not. theme-css.ts only emits `--cat-N` for a preset that ships a
   `tokens.palette` group, and 16 of the 18 presets ship none — `grep -L` over the
   generated sheets confirms it. On those sixteen an author who copies the
   gallery's six-ink card grid got `background: var(--cat-3)` with no such
   variable: an invalid value, so transparent background AND inherited text
   colour, i.e. six chips that silently stop being chips. The fallbacks below are
   the fix. `--accent-field` / `--accent-on-surface` exist in tokens.css for every
   theme, so a palette-less preset now degrades to one legible accent chip — the
   pre-B-084 look — instead of to nothing. A deck that HAS a palette is unaffected:
   a declared `--cat-N` always wins over its own fallback. */
.card .tag[data-cat] {
    display: inline-block;
    margin-bottom: 0.5rem;
    padding: 0.2em 0.6em;
    border-radius: var(--diagram-radius-pill);
    color: var(--on-cat-1, var(--accent-on-surface));
    background: var(--cat-1, var(--accent-field));
}
.card .tag[data-cat="1"] { background: var(--cat-1, var(--accent-field)); color: var(--on-cat-1, var(--accent-on-surface)); }
.card .tag[data-cat="2"] { background: var(--cat-2, var(--accent-field)); color: var(--on-cat-2, var(--accent-on-surface)); }
.card .tag[data-cat="3"] { background: var(--cat-3, var(--accent-field)); color: var(--on-cat-3, var(--accent-on-surface)); }
.card .tag[data-cat="4"] { background: var(--cat-4, var(--accent-field)); color: var(--on-cat-4, var(--accent-on-surface)); }
.card .tag[data-cat="5"] { background: var(--cat-5, var(--accent-field)); color: var(--on-cat-5, var(--accent-on-surface)); }
.card .tag[data-cat="6"] { background: var(--cat-6, var(--accent-field)); color: var(--on-cat-6, var(--accent-on-surface)); }
.card h3 { font-size: var(--h3-size); }
/* B-050: `.card.dim` — a de-emphasized card (Phase-2 / off-track / "later"
   items). The shipped examples already author `<div class="card dim">`, but the
   class was never defined anywhere in _shared, so a card meant to recede
   rendered pixel-identical to a live one — the contract the markup relied on was
   silently unmet. Fade it and dash the border so the step-down reads. */
.card.dim {
    opacity: 0.5;
    border-style: dashed;
}
.cards2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 25.6px;
    max-width: 880px;
    margin-inline: auto; /* B-116: not `margin: 0 auto` — see the .data-table note */
    width: 100%;
}

/* ─── Pill flow (compact inline sequence) ──────────────────────────────────
   A lighter alternative to .flow-diagram for inline term sequences. */
.pill-flow {
    display: flex;
    align-items: center;
    gap: 9.6px;
    flex-wrap: wrap;
}
.pill {
    background: var(--surface-bg);
    border: var(--diagram-border-width) solid var(--card-border);
    border-radius: var(--diagram-radius-pill);
    box-shadow: var(--surface-shadow);
    transition: var(--surface-transition);
    padding: 8.8px 16px;
    font-size: var(--small-size);
    font-weight: 600;
    color: var(--fg);
    white-space: nowrap;
}
/* B-088: both of these are accent labels on the pill/card ground, not on the page —
   same correction as `.card .tag` above. `.pill.hot` additionally paints
   --diagram-accent-tint (accent at 0.1) OVER that ground, which shifts it a little
   further; the derivation targets 4.6:1 rather than 4.5 precisely so a small extra
   layer does not push it back under. */
.pill.hot {
    border-color: var(--accent);
    color: var(--accent-on-surface);
    background: var(--diagram-accent-tint);
}
.pill-arrow { color: var(--accent-on-surface); font-size: var(--small-size); }

/* ─── Legacy patterns retained from the pre-B-004 set ──────────────────────
   timeline / inline-svg / data-cards stay so existing skeleton decks that use
   them keep rendering. They share the diagram radius/border vocabulary. */

/* timeline */
.timeline {
    position: relative;
    padding-left: 48px;
    max-width: 600px;
}
.timeline::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--card-border);
}
.timeline-item { position: relative; margin-bottom: 24px; }
.timeline-marker {
    position: absolute;
    left: calc(-1 * 48px + 2px);
    top: 4px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--bg-secondary);
    border: 2px solid var(--muted);
}
.timeline-marker.active {
    background: var(--accent);
    border-color: var(--accent);
    box-shadow: 0 0 12px var(--accent-glow);
}
.timeline-date {
    font-size: var(--small-size);
    color: var(--accent-text);
    font-weight: 600;
    margin-bottom: 0.2rem;
}
.timeline-content h4 { font-size: var(--body-size); font-weight: 600; color: var(--fg); }
.timeline-content p { font-size: var(--small-size); color: var(--muted); }

/* inline SVG */
.arch-diagram, .cycle-diagram {
    width: 100%;
    max-width: 800px;
    max-height: min(540px, 350px);
    margin-inline: auto; /* B-116: not `margin: 0 auto` — see the .data-table note */
    display: block;
}

/* data cards (KPI tiles) */
.data-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr));
    gap: 16px;
    max-width: 800px;
    margin-inline: auto; /* B-116: not `margin: 0 auto` — see the .data-table note */
}
.data-card {
    background: var(--surface-bg);
    border: var(--diagram-border-width) solid var(--card-border);
    border-radius: var(--diagram-radius);
    box-shadow: var(--surface-shadow);
    transition: var(--surface-transition);
    padding: 24px;
    text-align: center;
}
.data-value {
    font-size: 40px;
    font-weight: 800;
    color: var(--fg);
    letter-spacing: -0.02em;
}
.data-label { font-size: var(--small-size); color: var(--muted); margin-top: 0.2rem; }
.data-change { font-size: var(--small-size); font-weight: 600; margin-top: 0.3rem; }
.data-change.positive { color: var(--positive); }
.data-change.negative { color: var(--negative); }

/* ─── B-040: glass surface hover lift ──────────────────────────────────────
   Only the opt-in glass surfaces lift on hover, and only on true hover devices
   for users who haven't asked for reduced motion. Flat decks (the default) and
   touch/reduced-motion users get no transform — the tokens resolve to
   `0px` / `none` so even without this guard nothing would move, but scoping the
   selector to [data-surface="glass"] keeps the flat cascade untouched. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
    [data-surface="glass"] .card:hover,
    [data-surface="glass"] .layer:hover,
    [data-surface="glass"] .flow-step:hover,
    [data-surface="glass"] .cov-card:hover,
    [data-surface="glass"] .pill:hover,
    [data-surface="glass"] .data-card:hover {
        transform: translateY(var(--surface-hover-lift));
        box-shadow: var(--surface-hover-shadow);
    }
}

/* B-112: a viewport `@media` block used to live here — the narrow/short-stage
   folds. They are gone because they cannot be right on a fixed canvas: the canvas
   is always 1920x1080, so a rule keyed on the WINDOW would apply a small-screen
   fold to a full-size slide the moment someone shrank the browser. The problem
   they solved (content not fitting a small stage) is solved upstream now — the
   whole canvas scales, so the stage is never small in canvas pixels. Recovered
   from git history if a responsive canvas ever comes back. */
