/* common/shell.css — the shared application shell (chrome) for every SCML web tool.
   Token-based (see common/tokens.css); light default, OS-dark auto, explicit data-theme override.
   Linked AFTER tokens.css and BEFORE the app's own stylesheet, so an app can still override any rule.

   What lives here is the frame every tool shares, so a user who has worked in one recognises the next:
   the reset, the top header (brand · actions · language · theme), the button family, and the small
   shared controls (hint, switch, key-status, the i18n language select). App-specific layout — panes,
   cards, previews, dropzones, menus — stays in each app's own stylesheet. */

*,
*::before,
*::after { box-sizing: border-box; }

/* The `hidden` attribute must always win: class rules like `.ctl { display: flex }` are author styles
   that otherwise beat the UA `[hidden] { display: none }` rule and leak hidden controls into view. */
[hidden] { display: none !important; }

html,
body { height: 100%; }
body {
  margin: 0;
  display: flex;
  flex-direction: column;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--text);
  background: var(--bg);
}

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

/* ---- Header: brand on the left, actions pushed to the right, language + theme trailing ---- */
header {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: .6rem 1rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
  /* Stack above the layout so header dropdowns (Options/Layout) paint over panel bars (the sticky style
     bar creates its own stacking context). */
  position: relative;
  z-index: 50;
}
.brand { display: flex; align-items: center; gap: .6rem; min-width: 0; }
.brand-mark { color: var(--accent); display: inline-flex; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.brand-text h1 { font-size: 1.05rem; margin: 0; }
.brand-text .sub { font-size: .74rem; color: var(--text-dim); }

/* The action cluster. Every tool ends it with the same trailing pair — language selector, then the
   theme toggle — so that control is always in the same place from one tool to the next. */
.file-actions { margin-left: auto; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.fa-group { display: inline-flex; align-items: center; gap: .4rem; }

/* ---- Button family ---- */
.btn {
  font: inherit;
  font-size: .85rem;
  padding: .4rem .7rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  transition: background .14s ease, border-color .14s ease, color .14s ease, box-shadow .14s ease, transform .04s ease;
}
.btn:hover { background: var(--surface-2); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn:active { transform: translateY(1px); }
.btn-sm { font-size: .78rem; padding: .3rem .5rem; white-space: nowrap; }
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
/* Keep the accent background on hover; the generic .btn:hover would blank it to --surface-2 and leave
   the --accent-ink text unreadable. Brighten instead. */
.btn-primary:hover { background: var(--accent); filter: brightness(1.12); }

/* Icon button (the theme toggle): shows the moon in light mode, the sun in dark mode. */
.btn-icon { padding: .4rem .5rem; }
.btn-icon .theme-light { display: none; }
:root[data-theme="dark"] .btn-icon .theme-dark { display: none; }
:root[data-theme="dark"] .btn-icon .theme-light { display: inline; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn-icon .theme-dark { display: none; }
  :root:not([data-theme="light"]) .btn-icon .theme-light { display: inline; }
}

/* ---- Small shared controls ---- */
.hint { margin: 0 0 .6rem; font-size: .72rem; line-height: 1.45; color: var(--text-dim); }
.switch { display: flex; align-items: center; gap: .45rem; font-size: .82rem; cursor: pointer; }
.key-status {
  font-size: .72rem;
  color: var(--text-dim);
  padding: .15rem .45rem;
  border-radius: 999px;
  background: var(--muted-bg);
}
.key-status.ready { color: var(--ok); background: var(--ok-bg); }

/* The i18n language switcher, injected by common/i18n.js as <select class="lang-select">. */
.lang-select {
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-size: var(--text-md);
}

/* ---- Pane / section header (CC1): a titled bar with optional controls trailing on the right.
   The same component for every workspace section, so a section reads the same from tool to tool.
   An app may override the background/border to taste. ---- */
.pane-label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-xs);
  color: var(--text-dim);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.pl-title { text-transform: uppercase; letter-spacing: .06em; font-weight: 700; color: var(--text-dim); }
/* Per-slot panel picker in the pane header (next to the drag grip): choose which panel this slot shows.
   It replaces the static title, which is hidden to avoid redundancy (badges beside it stay). */
.zone-picker {
  font: inherit; font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-dim); background: transparent; border: 1px solid transparent; border-radius: var(--r-xs, 4px);
  padding: 1px 2px; max-width: 12rem; cursor: pointer;
}
.zone-picker:hover, .zone-picker:focus { border-color: var(--border); color: var(--text); }
.pane-label:has(.zone-picker) > .pl-title { display: none; }
/* With a slot picker present the header wraps: the grip + picker keep the top line, and everything
   after them (hint, badges, controls) drops to the next row via a full-width break element. */
.pane-label:has(.zone-picker),
summary:has(.zone-picker),
.se-bar:has(.zone-picker) { flex-wrap: wrap; }
.zone-picker-break { flex-basis: 100%; height: 0; margin: 0; padding: 0; }
.view-controls {
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-3);
}
.view-controls label { display: inline-flex; align-items: center; gap: var(--space-1); color: var(--text-dim); font-size: var(--text-sm); }

/* ---- Status pill (CC5): the app's own state. Colour AND a leading glyph, so state never relies on
   hue alone (colour-blind / low-vision). Idle is neutral; ok is accent; bad is the warn colour. ---- */
.status {
  margin-left: auto;
  white-space: nowrap;
  font-size: var(--text-sm);
  font-weight: 600;
  padding: var(--space-1) var(--space-3);
  border-radius: 999px;
  color: var(--text-dim);
  background: var(--surface-2);
  border: 1px solid var(--border);
}
.status.ok { color: var(--ok); background: var(--ok-bg); border-color: transparent; }
.status.bad { color: var(--warn); background: var(--warn-bg); border-color: transparent; }
.status.ok::before { content: "\2713\00a0"; font-weight: 700; }
.status.bad::before { content: "\26a0\00a0"; font-weight: 700; }

/* ---- Semantic context bar (both editors): a live breadcrumb of where the caret sits, under the
   document/template surface — section › block › cell/mark, the current mark highlighted. ---- */
.context-bar {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-4);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  font-size: var(--text-xs);
  color: var(--text-dim);
  min-height: 1.7rem;
}
.bc-crumb { white-space: nowrap; }
.bc-sep { color: var(--text-dim); opacity: .6; }
.bc-crumb.bc-mark { color: var(--accent); font-weight: 700; }
.bc-empty { color: var(--text-dim); opacity: .7; }

/* ---- Dropdown menu (a button that reveals a floating panel of secondary actions). Keeps a dense
   header legible: the everyday actions stay in the bar, the advanced ones live one click away. ---- */
.menu-wrap { position: relative; display: inline-flex; }
.menu-caret::after { content: " \25be"; font-size: .8em; opacity: .8; }
.menu-panel {
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  min-width: 12rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.menu-panel[hidden] { display: none; }
/* A labelled row inside the panel, so grouped actions read as a set. */
.menu-panel .menu-group-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .05em;
  font-weight: 700;
  color: var(--text-dim);
}

/* ---- Profile + packages control (both editors): a bar above the ribbon holding one dropdown that
   picks the semantic profile (radio) and toggles the optional domain packages (checkbox). ---- */
.profilebar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-1) var(--space-4);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.profile-panel { left: 0; right: auto; min-width: 14rem; } /* opens under the button, aligned left */
.menu-sep { height: 1px; background: var(--border); margin: var(--space-1) 0; }
/* A radio/checkbox row in a dropdown: a leading mark then the label; the active one is accented. */
.menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font: inherit;
  font-size: var(--text-sm);
  padding: var(--space-1) var(--space-2);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  text-align: left;
  width: 100%;
}
.menu-item:hover { background: var(--surface-2); }
.menu-item.on { color: var(--accent); font-weight: 600; }
.profile-mark { width: 1.1em; text-align: center; color: var(--text-dim); }
.menu-item.on .profile-mark { color: var(--accent); }
.menu-item[role="menuitemradio"] .profile-mark::before { content: "\25CB"; }       /* ○ */
.menu-item[role="menuitemradio"].on .profile-mark::before { content: "\25C9"; }    /* ◉ */
.menu-item[role="menuitemcheckbox"] .profile-mark::before { content: "\2610"; }    /* ☐ */
.menu-item[role="menuitemcheckbox"].on .profile-mark::before { content: "\2611"; } /* ☑ */

/* ---- Palette toolbar as a persistent ribbon (editor + template editor): a row of dimension tabs, and
   below it the active tab's insertable primitives, which stay put until you switch tabs (a caret at the
   end collapses the item row). Unlike a dropdown, nothing closes on a pick — easy to click in a row. ---- */
.ribbon-tabs { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); }
.ribbon-tab {
  font: inherit;
  font-size: var(--text-sm);
  padding: var(--space-1) var(--space-3);
  border: 1px solid transparent;
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}
.ribbon-tab { display: inline-flex; align-items: center; gap: .3em; }
.ribbon-tab:hover { color: var(--text); background: var(--surface-2); }
.ribbon-tab.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
/* Drag handle to reorder ribbon groups; visible on hover so it stays unobtrusive. */
.ribbon-grip { cursor: grab; opacity: 0; font-size: .85em; line-height: 1; color: var(--text-dim); transition: opacity .1s; }
.ribbon-tab:hover .ribbon-grip { opacity: .55; }
.ribbon-grip:hover { opacity: .9; }
.ribbon-grip:active { cursor: grabbing; }
/* Keyboard users must be able to see and locate the reorder handle when it takes focus. */
.ribbon-grip:focus-visible { opacity: 1; outline: 2px solid var(--accent, #4a7); outline-offset: 2px; border-radius: 3px; }
.ribbon-tab.dragging { opacity: .45; }
.ribbon-tab.drop-target { box-shadow: inset 3px 0 0 var(--accent); }
/* Below the toggles: the open groups flow inline next to each other (like ribbon groups), wrapping only
   when the row is full — each group labelled and separated by a thin rule, to save vertical space. */
.ribbon-body {
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  padding-top: var(--space-2);
  margin-top: var(--space-1);
  border-top: 1px solid var(--border);
}
.ribbon-body[hidden] { display: none; }
.ribbon-section { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); }
.ribbon-section + .ribbon-section { padding-left: var(--space-3); border-left: 1px solid var(--border); }
.ribbon-section-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .05em;
  font-weight: 700;
  color: var(--text-dim);
}
.tb-item {
  font: inherit;
  font-size: var(--text-sm);
  padding: var(--space-1) var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.tb-item:hover { background: var(--surface-2); border-color: var(--border-strong); color: var(--accent); }

/* An emphasized ribbon action (the Recognize scan): a filled accent pill that stands out from the
   plain mark buttons, sitting right after its group label. */
.tb-item.tb-accent {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  font-weight: 600;
  margin-right: var(--space-2);
}
.tb-item.tb-accent:hover { background: var(--accent); filter: brightness(1.12); color: var(--accent-ink); }

/* ---- Structure-builder dialogs (table / list wizards, shared by both editors — see common/builders.js).
   The `.dialog` base comes from each app's own CSS; only the builder-specific parts live here, written in
   the shared token vocabulary so they render identically in both. ---- */
.dialog.builder { min-width: 30rem; }
.builder-ctrl { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; font-size: .85rem; padding-bottom: .3rem; }
.builder-num { display: inline-flex; align-items: center; gap: .4rem; color: var(--text-dim); }
.builder-num input { width: 4rem; font: inherit; font-size: .82rem; padding: .3rem .4rem; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface); color: var(--text); }
.builder-num input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
.builder-check { display: inline-flex; align-items: center; gap: .4rem; color: var(--text-dim); }
.builder-grid-wrap { max-height: 50vh; overflow: auto; padding: .1rem; }
.builder-grid { display: grid; gap: .35rem; }
.builder-grid input { font: inherit; font-size: .82rem; padding: .35rem .45rem; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface); color: var(--text); min-width: 0; }
.builder-grid input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
.builder-items { font: inherit; font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace; font-size: .85rem; padding: .55rem; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); resize: vertical; background: var(--surface); color: var(--text); }
.builder-items:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }

/* Guided onboarding tour (common/onboarding.js): a dimmed overlay, a ring around the highlighted
   element, and an anchored tooltip with Back / Next / Skip. Shared by the web editors. */
.tour-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, .45); z-index: 4000; }
.tour-ring { position: fixed; z-index: 4001; border-radius: 6px; box-shadow: 0 0 0 3px var(--accent, #4a7), 0 0 0 9999px rgba(0, 0, 0, .001); pointer-events: none; transition: left .18s, top .18s, width .18s, height .18s; }
.tour-tip { position: fixed; z-index: 4002; width: min(22rem, 92vw); background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); border-radius: var(--radius, 8px); box-shadow: 0 10px 30px rgba(0, 0, 0, .3); padding: .9rem 1rem; }
.tour-tip-title { margin: 0 0 .4rem; font-size: 1rem; font-weight: 600; }
.tour-tip-body { margin: 0 0 .8rem; font-size: .85rem; line-height: 1.4; color: var(--text-dim); }
.tour-tip-nav { display: flex; align-items: center; gap: .4rem; }
.tour-tip-progress { margin-right: auto; font-size: .75rem; color: var(--text-dim); }
.tour-btn { font: inherit; font-size: .82rem; padding: .35rem .7rem; border: 1px solid var(--border-strong); border-radius: var(--radius-sm, 6px); background: var(--surface); color: var(--text); cursor: pointer; }
.tour-btn.tour-next { background: var(--accent); color: var(--accent-ink, #fff); border-color: var(--accent); }
.tour-btn:disabled { opacity: .5; cursor: default; }
.tour-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
