/*
 * Print Preview Stylesheet
 * Handles both screen preview and @media print for actual printing.
 * Used by the print layout (app/views/layouts/print.html.erb).
 *
 * NOTE: This file is auto-loaded by Propshaft via stylesheet_link_tag :app.
 * All rules MUST be scoped to .print-container or print-specific classes
 * to avoid polluting the main application styles.
 */

/* ============================================
   Scoped Reset (print layout only)
   ============================================ */
.print-container *,
.print-container *::before,
.print-container *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.print-container {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  line-height: 1.3;
  color: #000;
}

/* ============================================
   Page Container
   ============================================ */
.print-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  padding: 20px;
}

.print-page {
  background: #fff;
  position: relative;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
}

/* Page sizes */
.print-page--letter {
  width: 8.5in;
  min-height: 11in;
}

.print-page--a4 {
  width: 8.27in;
  min-height: 11.69in;
}

/* Wristband pages use inline width/height from settings */
.print-page--wristband {
  /* width and height set via inline style from wristband dimensions */
}

/* Wristband sheet: physical page containing tiled wristband cards */
.print-page--wristband-sheet {
  /* Override inherited flex/min-height so cards pack flush */
  display: block !important;
  min-height: 0 !important;
  height: auto !important;
  position: relative;
}

.wristband-sheet-grid {
  /* grid-template set via inline style; no gap between cards */
  display: grid !important;
  gap: 0 !important;
  align-content: start;
  justify-content: start;
}

.wristband-card {
  border: none;
  display: flex;
  flex-direction: column;
  position: relative;
}

.wristband-card .print-grid {
  flex: 1;
  border: none;
}

.wristband-card .print-watermark-logo {
  max-width: 120px;
  max-height: 120px;
}

.wristband-card .print-watermark-text {
  font-size: 32px;
  letter-spacing: 4px;
}

.wristband-card .print-footer {
  font-size: 5px;
}

.wristband-card .print-cell-header,
.print-cell-header--wristband {
  font-size: 7px;
  padding: 1px 3px;
  min-height: 12px;
}

.wristband-card .print-cell-header .play-number {
  width: 10px;
  height: 10px;
  font-size: 6px;
}

/* ============================================
   Watermark
   ============================================ */
.print-watermark {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-30deg);
  opacity: 0.04;
  pointer-events: none;
  z-index: 0;
  user-select: none;
}

.print-watermark-logo {
  max-width: 400px;
  max-height: 400px;
  width: auto;
  height: auto;
}

.print-watermark-text {
  font-size: 96px;
  font-weight: 900;
  letter-spacing: 12px;
  color: #000;
  white-space: nowrap;
}

/* ============================================
   Grid / Wristband Mode
   ============================================ */
.print-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  gap: 0;
  position: relative;
  z-index: 1;
  border: 2px solid #000;
}

.print-cell {
  border: 1px solid #000;
  display: flex;
  flex-direction: column;
  overflow: visible;
  min-height: 0;
}

.print-cell--empty {
  /* Empty cells just show border */
}

.print-cell-header {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  font-size: 10px;
  font-weight: bold;
  border-bottom: 1px solid #000;
  min-height: 18px;
  flex-shrink: 0;
}

.print-cell-title {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.print-cell-diagram {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0;
  min-height: 0;
  overflow: visible;
}

.print-cell-diagram svg {
  max-width: 100%;
  max-height: 100%;
}

/* ============================================
   #240 — Optional per-play tag strip
   (rendered between .print-cell-header and
   .print-cell-diagram only when tag_display is
   "full" or "colour"; never for the default
   "none", so the layout is unchanged when off)

   Design tokens (print output is ALWAYS light, so
   these stay fixed regardless of screen theme):
     --print-tag-blank      blank/invalid tag colour fallback (AA with white, 4.8:1)
     --print-tag-more-bg    "+N" overflow chip background
     --print-tag-more-text  "+N" overflow chip text
   Tag COLOURS themselves are user data (Tag.color)
   and are applied inline by the view — no new brand
   colours are invented here.
   ============================================ */
:root {
  --print-tag-blank: #71717a;
  --print-tag-more-bg: #d4d4d4;
  --print-tag-more-text: #404040;
}

/* The strip: a thin, single-line band that never
   steals diagram height (flex-shrink:0 + nowrap). */
.print-cell-tags {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  min-height: 16px;
  overflow: hidden;
  flex-shrink: 0;
  white-space: nowrap;
  border-bottom: 1px solid #000;
  background: rgba(0, 0, 0, 0.015);
}

/* Wristband scale: tighter band to match the 7px header. */
.wristband-card .print-cell-tags {
  gap: 2px;
  padding: 1px 3px;
  min-height: 11px;
}

/* Colour pill: tag-colour background (inline) +
   WCAG auto-contrast name. min-width:0 + the inner
   .ptl span let a long name ellipsise INSIDE the pill
   (text-overflow does not work on the inline-flex pill). */
.print-tag-pill {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 0 6px;
  border-radius: 999px;
  font-size: 9px;
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
  min-width: 0;
  max-width: 100%;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

.print-tag-pill .ptl {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.wristband-card .print-tag-pill {
  font-size: 6px;
  padding: 0 4px;
}

/* Full-text mode: plain names joined by a middot,
   truncated with an ellipsis on a single line. */
.print-tag-text {
  font-size: 9px;
  font-weight: 600;
  color: #1c1917;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.print-tag-text .sep {
  color: #a8a29e;
  font-weight: 700;
  padding: 0 4px;
}

.wristband-card .print-tag-text {
  font-size: 6px;
}

/* "+N" overflow counter chip (neutral, never a pill). */
.print-tag-more {
  display: inline-flex;
  align-items: center;
  padding: 0 7px;
  border-radius: 999px;
  font-size: 9px;
  font-weight: 700;
  line-height: 1.5;
  flex-shrink: 0;
  background: var(--print-tag-more-bg);
  color: var(--print-tag-more-text);
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

.wristband-card .print-tag-more {
  font-size: 6px;
  padding: 0 5px;
}

/* ============================================
   Play Number Badge
   ============================================ */
.play-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  flex-shrink: 0;
  line-height: 1;
}

.play-number--circle {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: 11px;
}

.play-number--square {
  width: 22px;
  height: 22px;
  border-radius: 3px;
  font-size: 11px;
}

.play-number--diamond {
  width: 22px;
  height: 22px;
  border-radius: 2px;
  transform: rotate(45deg);
  font-size: 10px;
}

.play-number--diamond > * {
  transform: rotate(-45deg);
}

/* Smaller variants for grid cells */
.print-cell-header .play-number {
  width: 16px;
  height: 16px;
  font-size: 9px;
}

.print-cell-header .play-number--diamond {
  width: 16px;
  height: 16px;
  font-size: 8px;
}

/* ============================================
   Text Play Content
   ============================================ */
.text-play-print {
  white-space: pre-wrap;
  word-wrap: break-word;
  font-size: 14px;
  line-height: 1.5;
  padding: 12px;
  text-align: left;
}

.text-play-print--small {
  font-size: 9px;
  line-height: 1.3;
  padding: 4px;
}

/* ============================================
   Calibration Rulers (print debug)
   ============================================ */
.print-ruler {
  position: absolute;
  z-index: 10;
}

.print-ruler--right {
  top: 0;
  width: 0.25in;
}

.print-ruler--right::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1px;
  background: #000;
}

.print-ruler--bottom {
  position: absolute;
  height: 0.25in;
}

.print-ruler--bottom::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: #000;
}

.print-ruler .ruler-tick {
  position: absolute;
}

/* Right ruler ticks (horizontal lines from left edge) */
.print-ruler--right .ruler-tick--major {
  left: 0;
  width: 8px;
  border-top: 1px solid #000;
}

.print-ruler--right .ruler-tick--major span {
  position: absolute;
  left: 10px;
  top: -5px;
  font-size: 6px;
  font-family: Arial, sans-serif;
  color: #000;
}

.print-ruler--right .ruler-tick--minor {
  left: 0;
  width: 4px;
  border-top: 1px solid #000;
}

/* Bottom ruler ticks (vertical lines from top edge) */
.print-ruler--bottom .ruler-tick--major {
  top: 0;
  height: 8px;
  border-left: 1px solid #000;
}

.print-ruler--bottom .ruler-tick--major span {
  position: absolute;
  top: 10px;
  left: -3px;
  font-size: 6px;
  font-family: Arial, sans-serif;
  color: #000;
}

.print-ruler--bottom .ruler-tick--minor {
  top: 0;
  height: 4px;
  border-left: 1px solid #000;
}

/* ============================================
   Footer / Identifier
   ============================================ */
.print-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 4px;
  margin-top: auto;
  font-size: 7px;
  color: #999;
  border-top: 0.5px solid #ddd;
  position: relative;
  z-index: 1;
}

.print-id {
  font-family: 'Courier New', monospace;
  font-weight: bold;
  letter-spacing: 1px;
}

.print-meta {
  text-align: right;
}

/* ============================================
   Print Config Form Styles
   (scoped to .print-config-form to avoid leaking)
   ============================================ */
.print-config-form .btn-group { display: flex; gap: 0.25em; }
.print-config-form .btn-group-vertical { flex-direction: column; }

.print-config-form .grid-btn {
  background: var(--bg-tertiary, #e7e5e4);
  color: var(--text-color, #292524);
  border: none;
  border-radius: 6px;
  padding: 0.4em 0.8em;
  font-size: 1em;
  cursor: pointer;
  margin-bottom: 0.2em;
  transition: box-shadow 0.2s, background 0.2s;
  min-width: 2.5em;
  min-height: 2.5em;
  display: flex;
  align-items: center;
  justify-content: center;
}

.print-config-form .grid-btn.active,
.print-config-form .grid-btn:focus {
  background: #b45309 !important;
  color: #fff !important;
  outline: none;
  border: none;
}

.print-config-form .grid-btn:hover {
  background: #fffbeb;
  box-shadow: 0 0 0 2px rgba(180, 83, 9, 0.6);
}

.print-config-form .preset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
  gap: 0.25em;
  margin-bottom: 0.2em;
}

.print-config-form .preset-grid-2x3 {
  grid-template-columns: repeat(3, 1fr);
}

/* For wristband presets that include 7 items (6 brands + Custom) */
.print-config-form .preset-grid-2x3 .preset-btn:nth-child(7) {
  grid-column: 2;
}

.print-config-form .preset-btn {
  font-size: 0.95em;
  padding: 0.3em 0.7em;
  margin: 0;
  min-width: 90px;
  min-height: 2.5em;
}

.print-config-form .print-style-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.75em;
  /* #310: bottom-align cells so swatches/inputs line up on a common baseline
     regardless of how many lines a label wraps to (e.g. the 3-line
     "Header Background (fallback)" label in formation mode). Without this a
     multi-line label pushes its control down out of line with its neighbours. */
  align-items: end;
}

.print-config-form .form-color-input {
  width: 50px;
  height: 32px;
  padding: 2px;
  cursor: pointer;
}

.print-config-form .btn-group-rows > button,
.print-config-form .btn-group-cols > button {
  flex: 1 1 0;
  min-width: 0;
}

/* ============================================
   @media print — Actual printing
   ============================================ */
@media print {
  .print-container {
    background: white;
    padding: 0;
    gap: 0;
  }

  .print-page {
    box-shadow: none;
    page-break-after: always;
    break-after: page;
  }

  .print-page:last-child {
    page-break-after: avoid;
    break-after: avoid;
  }

  /* Force exact colors */
  .print-container * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
    color-adjust: exact !important;
  }

  /* Ensure watermark prints */
  .print-watermark {
    opacity: 0.04 !important;
  }

  /* Hide any browser chrome */
  @page {
    margin: 0;
  }
}

/* ============================================
   Dark Mode overrides for config form only
   (print preview always uses light/white)
   ============================================ */
html.dark-mode .print-config-form .grid-btn {
  background: #44403c;
  color: #d6d3d1;
}

html.dark-mode .print-config-form .grid-btn:hover {
  background: #57534e;
}

html.dark-mode .print-config-form .grid-btn.active {
  background: #b45309 !important;
  color: #fff !important;
}

/* ============================================
   Play Header Colour (#239) — per-play overrides, source control,
   picker, preview strip + contrast pill.
   Scoped to .print-config-form so it never leaks elsewhere.
   All colours are design tokens from variables.css (no hardcoding); the
   custom properties above re-define themselves under html.dark-mode.
   ============================================ */

/* --- Header colour source block --- */
.print-config-form .hc-source { display: flex; flex-direction: column; gap: var(--spacing-xs); }
/* Hint stays in normal flow (not flex) so inline <strong> words sit on baseline. */
.print-config-form .hc-hint { font-size: 0.8rem; color: var(--text-muted); line-height: 1.45; margin-top: 0.5em; }
.print-config-form .hc-hint .dot { display: inline-block; width: 0.75em; height: 0.75em; border-radius: 50%; border: 1px solid rgba(0,0,0,0.18); vertical-align: -0.05em; margin-right: 0.3em; }

/* --- Per-play overrides <details> --- */
.print-config-form .override-details { border: 1px solid var(--border-color); border-radius: var(--radius-md); background: var(--bg-secondary); margin-top: var(--spacing-md); }
.print-config-form .override-details > summary { list-style: none; cursor: pointer; padding: 0.6rem 0.75rem; display: flex; align-items: center; gap: 0.5rem; font-weight: 600; font-size: 0.9rem; color: var(--text-color); }
.print-config-form .override-details > summary::-webkit-details-marker { display: none; }
.print-config-form .override-details > summary .chev { transition: transform 0.15s; color: var(--text-subtle); }
.print-config-form .override-details[open] > summary .chev { transform: rotate(90deg); }
.print-config-form .override-count { margin-left: auto; font-size: 0.75rem; font-weight: 600; color: var(--text-muted); background: var(--bg-tertiary); border-radius: 999px; padding: 0.1rem 0.55rem; }
/* #299: orientation line at the top of the overrides panel — explains the toggle
   and the hex format ONCE, so we don't repeat helper text on every row. */
.print-config-form .override-intro { font-size: 0.8rem; color: var(--text-muted); line-height: 1.5; padding: 0.15rem 0.75rem 0.6rem; }
.print-config-form .override-intro code { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 0.75rem; padding: 1px 5px; border-radius: var(--radius-sm); background: var(--bg-tertiary); color: var(--text-color); }
.print-config-form .override-list { padding: 0.25rem 0.75rem 0.75rem; display: flex; flex-direction: column; }

/* Robust single flex row that wraps — every element always renders. */
.print-config-form .override-row { display: flex; align-items: center; gap: 0.35rem 0.6rem; flex-wrap: wrap; padding: 0.6rem 0; border-top: 1px solid var(--border-color); }
.print-config-form .override-row:first-child { border-top: none; }
.print-config-form .or-idx { font-size: 0.75rem; font-weight: 700; color: var(--text-subtle); min-width: 1rem; text-align: center; flex: 0 0 auto; }
.print-config-form .or-name { display: flex; align-items: baseline; gap: 0.4rem; min-width: 0; flex: 1 1 auto; }
.print-config-form .or-name .nm { font-weight: 600; font-size: 0.875rem; color: var(--text-color); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.print-config-form .or-formation { font-size: 0.72rem; color: var(--text-muted); font-weight: 500; flex: 0 0 auto; }
.print-config-form .or-resolved { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.75rem; color: var(--text-muted); margin-left: auto; flex: 0 0 auto; word-break: break-all; }
/* #299: resolved chip reads "<Named source> · #HEX" — the source name is emphasised,
   the hex is muted. Replaces the ambiguous "Fallback" word. */
.print-config-form .or-resolved .src { font-weight: 600; color: var(--text-color); }
.print-config-form .or-resolved .chip-hex { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; color: var(--text-muted); }
.print-config-form .or-ctrl { display: inline-flex; align-items: center; gap: 0.4rem 0.6rem; flex: 0 0 auto; flex-wrap: wrap; }

/* small resolved / target colour chip */
.print-config-form .chip-swatch { width: 1.15rem; height: 1.15rem; border-radius: var(--radius-sm); border: 1px solid rgba(0,0,0,0.18); flex-shrink: 0; background-size: cover; background-position: center; }
/* #307: dark-mode parity — the light-mode black border vanishes on a dark card,
   so lift it to a white hairline (matches the mockup). */
html.dark-mode .print-config-form .chip-swatch { border-color: rgba(255,255,255,0.28); }
.print-config-form .chip-swatch.is-auto { background: repeating-linear-gradient(45deg, var(--text-subtle), var(--text-subtle) 2px, var(--bg-tertiary) 2px, var(--bg-tertiary) 5px); }
/* #307: in dark mode the token-driven hatch is too dark to read as "auto"; use the
   mockup's lighter warm-stone hatch so the auto state stays visible. */
html.dark-mode .print-config-form .chip-swatch.is-auto { background: repeating-linear-gradient(45deg, #8a837c, #8a837c 2px, #3a352f 2px, #3a352f 5px); }

/* override toggle switch */
.print-config-form .override-toggle { position: relative; display: inline-flex; align-items: center; width: 34px; height: 20px; border-radius: 999px; background: var(--bg-tertiary); border: 1px solid var(--border-color); cursor: pointer; transition: background 0.15s; flex-shrink: 0; }
.print-config-form .override-toggle .knob { position: absolute; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,0.3); transition: left 0.15s; }
.print-config-form .override-toggle[aria-checked="true"] { background: var(--primary); border-color: var(--primary); }
.print-config-form .override-toggle[aria-checked="true"] .knob { left: 16px; }

/* #299: labelled override toggle — a visible "Custom colour" label bound to the
   switch so its purpose is explicit (no more bare, unlabeled switch). */
.print-config-form .toggle-field { display: inline-flex; align-items: center; gap: 0.45rem; flex: 0 0 auto; }
.print-config-form .toggle-field .toggle-label { font-size: 0.78rem; font-weight: 600; color: var(--text-color); white-space: nowrap; }

/* active override colour control (popover trigger button + labelled hex) */
.print-config-form .override-color { display: inline-flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
/* #307: the row swatch is now a POPOVER TRIGGER button, not a native
   <input type="color">. Clicking it opens ONLY the custom popover — the OS
   picker lives inside the popover as the "Custom colour" control. The visible
   colour is the `.swatch-fill` child (painted by JS from the resolved colour). */
.print-config-form .swatch-trigger {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 30px; padding: 0;
  border: 1px solid var(--input-border); border-radius: var(--radius-md);
  background: var(--input-bg); cursor: pointer; flex-shrink: 0;
  transition: box-shadow 0.15s, border-color 0.15s;
}
.print-config-form .swatch-trigger .swatch-fill {
  width: 24px; height: 20px; border-radius: 3px;
  border: 1px solid rgba(0, 0, 0, 0.18);
}
html.dark-mode .print-config-form .swatch-trigger .swatch-fill { border-color: rgba(255, 255, 255, 0.28); }
.print-config-form .swatch-trigger:hover { border-color: var(--border-focus); box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.35); }
.print-config-form .swatch-trigger .caret {
  position: absolute; right: 1px; bottom: 0;
  font-size: 0.62rem; font-weight: 700; color: var(--text-muted); line-height: 1;
}
/* when the row is auto (override off) the trigger reads as inactive */
.print-config-form .override-row.is-auto .swatch-trigger { opacity: 0.5; }
/* #299: labelled hex input — "Hex" label above the field, grouped with the swatch
   so the relationship (hex is the typed value of the swatch) is obvious.
   Display is uppercased (mockup casing); the submitted value is unaffected. */
.print-config-form .hex-field { display: inline-flex; flex-direction: column; gap: 2px; }
.print-config-form .hex-field .hex-label { font-size: 0.66rem; font-weight: 700; letter-spacing: 0.02em; color: var(--text-muted); text-transform: uppercase; }
.print-config-form .hex-field .hex-input { width: 92px; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 0.78rem; padding: 0.3rem 0.5rem; text-transform: uppercase; }
/* #307: non-destructive hex typing states.
   is-typing  — an intermediate (still-invalid) value: calm focus ring + a
                "keep typing" hint. The text is KEPT (never wiped mid-type).
   is-invalid — committed-invalid (blurred on a bad value): red ring + hint.
   NOTE: the border-color needs `!important` because forms_dark.css resets every
   `input` to `border: 1px solid var(--input-border) !important`; without it the
   amber/red state border is silently overridden and only the glow shows. */
.print-config-form .hex-field.is-typing .hex-input {
  border-color: var(--border-focus) !important;
  box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.12);
  color: var(--input-text);
}
.print-config-form .hex-field.is-invalid .hex-input {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 3px rgba(var(--danger-rgb), 0.15);
}
.print-config-form .validation-hint {
  display: none;
  font-size: 0.66rem; font-weight: 600; color: var(--danger);
  margin-top: 2px; white-space: nowrap;
}
.print-config-form .hex-field.is-invalid .validation-hint { display: block; }
.print-config-form .typing-hint {
  display: none;
  font-size: 0.66rem; font-weight: 600; color: var(--text-muted);
  margin-top: 2px; white-space: nowrap;
}
.print-config-form .hex-field.is-typing .typing-hint { display: block; }
.print-config-form .reset-btn { border: none; background: none; color: var(--text-subtle); cursor: pointer; font-size: 0.75rem; padding: 0.15rem 0.3rem; border-radius: var(--radius-sm); align-self: center; }
.print-config-form .reset-btn:hover { color: var(--danger); background: rgba(var(--danger-rgb), 0.1); }

/* #307: the auto-row "inactive" look is carried by the TRIGGER-level dim
   (`.override-row.is-auto .swatch-trigger { opacity: 0.5 }`, line 614) plus the
   muted hex text below — NOT by a wrapper-level opacity on `.override-color`.
   A wrapper opacity would also dim the `.picker-pop` popover, which is a
   DESCENDANT of `.override-color` (it anchors to the swatch via `.picker-wrap`).
   CSS opacity on an ancestor composites its whole subtree translucent and CANNOT
   be undone by a descendant, so the popover's colour input / hex / contrast pill
   / Reset bled page text through on auto rows. The wrapper dim is therefore
   removed: the trigger dim alone keeps the auto row reading as inactive, while
   the popover stays fully opaque on every row type. (Inputs remain present so
   the value is still submitted.) */
.print-config-form .override-row.is-auto .hex-field .hex-input { color: var(--text-muted); }
/* #299: the in-row reset only makes sense once a custom colour is set — hide it while auto. */
.print-config-form .override-row.is-auto .reset-btn { display: none; }

/* --- colour picker popover (opens UPWARD so it never covers content below) --- */
.print-config-form .picker-wrap { position: relative; display: inline-flex; align-items: center; }
.print-config-form .picker-pop { position: absolute; bottom: calc(100% + 6px); right: 0; z-index: 40; background: var(--card-bg); border: 1px solid var(--card-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-md); padding: 0.75rem; width: 224px; }
.print-config-form .picker-pop.is-open { display: flex; flex-direction: column; }
.print-config-form .picker-pop.is-hidden { display: none; }
.print-config-form .picker-pop .swatches { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; margin-bottom: 0.6rem; }
.print-config-form .picker-pop .sw { width: 100%; aspect-ratio: 1; border-radius: var(--radius-sm); border: 1px solid rgba(0,0,0,0.15); cursor: pointer; }
/* #307: dark-mode parity — lift the swatch border so the light swatches
   (#ffffff / #f0f0f0) stay delineated against the dark popover card. */
html.dark-mode .print-config-form .picker-pop .sw { border-color: rgba(255,255,255,0.25); }
.print-config-form .picker-pop .sw.sel { outline: 2px solid var(--border-focus); outline-offset: 1px; }
.print-config-form .picker-pop .row { display: flex; align-items: center; gap: 0.5rem; }
.print-config-form .picker-pop .row input[type="color"] { width: 34px; height: 30px; padding: 2px; border: 1px solid var(--input-border); border-radius: var(--radius-md); background: var(--input-bg); cursor: pointer; flex-shrink: 0; }
.print-config-form .picker-pop .row .hex { flex: 1 1 auto; min-width: 0; box-sizing: border-box; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 0.8rem; text-transform: uppercase; }
.print-config-form .picker-pop .foot { display: flex; justify-content: space-between; align-items: center; margin-top: 0.6rem; }

/* =====================================================================
   #314 — SHARED contrast-pill component (#316).
   ---------------------------------------------------------------------
   Extracted from the old `.print-config-form .contrast-pill` (was scoped) into
   an UNSCOPED shared component so both contrast surfaces render from ONE source
   and can never drift:
     * the per-play picker pill  (print_config.js#renderContrastPill → 2 tiers),
     * the global Header Text pill (#header_text_contrast slot → 3 tiers).
   The className/skin contract is owned by print_config.js#paintContrastPill:
   `.contrast-pill.ok` / `.contrast-pill.warn` / `.contrast-pill.fail`, with
   `.cp-ico` (decorative), `.cp-label`, `.cp-ratio` (tabular-nums) children.
   Foregrounds use the AA-safe --contrast-*-fg readability tokens (the shipped
   --success / --primary text failed AA at 0.7rem; see variables.css #314 note).
   ===================================================================== */
.contrast-pill { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.7rem; font-weight: 700; line-height: 1.4; padding: 0.12rem 0.5rem; border-radius: 999px; white-space: nowrap; }
.contrast-pill .cp-ico { font-size: 0.85em; line-height: 1; flex: 0 0 auto; }
.contrast-pill .cp-ratio { font-variant-numeric: tabular-nums; }
.contrast-pill.ok { color: var(--contrast-ok-fg); background: var(--contrast-ok-bg); }
/* WARN + FAIL share the amber caution skin (#307 precedent): this is a CAUTION
   (the header may be hard to read), NOT a hard error, so it uses the amber
   `--primary` family rather than `--danger` red — red fails AA on the dark tint
   (~2.86:1) and reads as "blocked", contradicting the ADVISORY contract (#314). */
.contrast-pill.warn { color: var(--contrast-warn-fg); background: var(--contrast-warn-bg); }
/* FAIL (#314): amber caution with a deeper tint — escalated ONLY via the ✕ glyph
   (JS-owned) + stronger copy, never red. 2 skins serve 3 tiers; no new hue. */
.contrast-pill.fail { color: var(--contrast-warn-fg); background: var(--contrast-fail-bg); }

/* Placement slot — a full-width advisory line rendered as a SIBLING directly
   under the .print-style-grid (NOT inside a grid cell: the grid is
   `align-items: end`, so an in-cell pill grows the cell and reflows the row).
   Mirrors the .hc-source / .hc-hint blocks that already sit outside the grid, so
   a pill appearing never shifts the controls. role=status / aria-live=polite set
   in the ERB; recompute debounced in JS. No CSS animation → reduced-motion needs
   no special case. Wraps gracefully on narrow viewports. */
.contrast-slot { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.4rem; flex-wrap: wrap; }
.contrast-note { font-size: 0.72rem; color: var(--text-muted); line-height: 1.35; flex: 1 1 10rem; }

/* --- printed-header preview (ALL roles) --- */
/* #299: preview title (replaces the old inline margin-top) + role-aware caption. */
.print-config-form .preview-title { margin-top: var(--spacing-md); }
.print-config-form .preview-caption { font-size: 0.8rem; color: var(--text-muted); margin: 0 0 0.5rem; display: flex; align-items: center; gap: 0.4rem; }
/* role badges on the preview caption */
.print-config-form .role-badge { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.7rem; font-weight: 700; padding: 0.12rem 0.55rem; border-radius: 999px; letter-spacing: 0.01em; }
.print-config-form .role-badge.manager { color: var(--primary); background: var(--primary-transparent); }
.print-config-form .role-badge.viewer { color: var(--text-muted); background: var(--bg-tertiary); }
.print-config-form .preview-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.75rem; margin-top: 0; }
.print-config-form .mini-cell { border: 1px solid var(--card-border); border-radius: var(--radius-md); overflow: hidden; background: var(--card-bg); box-shadow: var(--shadow-sm); }
.print-config-form .mini-cell .mini-head { display: flex; align-items: center; gap: 0.4rem; padding: 0.35rem 0.5rem; font-size: 0.78rem; font-weight: 600; color: #fff; }
.print-config-form .mini-cell .mini-num { display: inline-flex; align-items: center; justify-content: center; width: 1.15rem; height: 1.15rem; border-radius: 50%; font-size: 0.7rem; font-weight: 700; flex-shrink: 0; }
.print-config-form .mini-cell .mini-body { height: 46px; background: repeating-linear-gradient(0deg, #2f7d3b, #2f7d3b 10px, #358a43 10px, #358a43 20px); }

/* --- accessible focus for the new interactive controls (keyboard users) --- */
.print-config-form .grid-btn:focus-visible,
.print-config-form .override-toggle:focus-visible,
.print-config-form .swatch-trigger:focus-visible,
.print-config-form .hex-field .hex-input:focus-visible,
.print-config-form .reset-btn:focus-visible,
.print-config-form .picker-pop *:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--card-bg), 0 0 0 4px var(--border-focus);
}

/* #239 keyboard focus: guarantee a visible ring on the segmented grid-buttons.
   Placed last with !important so it cannot be suppressed by earlier active/focus rules. */
.print-config-form .grid-btn:focus-visible {
  outline: none !important;
  box-shadow: 0 0 0 2px var(--card-bg), 0 0 0 4px var(--border-focus) !important;
}
