/* ============================================================
   ORA CANON · cross-page canonical components (00-global-patterns
   §32 viz-card · §33 async states · §34 slide-out).
   Loaded by every canonical page AFTER its own styles; rules are
   written at low specificity (:where) where pages already carry a
   correct local definition, and as alignment overrides where the
   spec demands cross-page uniformity. Tokens only, zero raw hex.
   ============================================================ */

/* ---- §32 canonical viz card -------------------------------------
   Contract: .tile[data-canonical-tile] with .tile-head (.tile-title
   + .tile-sub left, .tile-tools right). The viz-switch cog (.gear)
   appears only when the tile has alternate renders (config);
   the card chrome is identical everywhere. */
:where(.tile){ background:var(--surface); border:1px solid var(--border-subtle); border-radius:var(--radius-lg); }
.tile .gear, .tile-tools .gear{
  background:transparent; border:0; color:var(--text-tertiary); cursor:pointer;
  padding:4px 6px; border-radius:var(--radius-pill); font-size:12px;
  transition:color var(--duration-fast,0.15s) var(--ease,ease), background var(--duration-fast,0.15s) var(--ease,ease);
}
.tile .gear:hover, .tile-tools .gear:hover{ color:var(--accent); background:var(--glass-bg); }
.tile .var-badge{
  font-family:var(--font-mono); font-size:var(--text-2xs,9px); letter-spacing:.08em;
  text-transform:uppercase; color:var(--text-tertiary); background:var(--glass-bg);
  border-radius:var(--radius-pill); padding:2px 8px;
}

/* ---- §33 canonical async states ---------------------------------
   Skeleton first, then real data or the honest empty state.
   Pages ship .skel in their initial markup; no sample data ever. */
:where(.skel){
  position:relative; overflow:hidden; border-radius:var(--radius-md);
  background:var(--glass-bg);
}
.skel::after{
  content:''; position:absolute; inset:0;
  background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--text) 6%, transparent), transparent);
  animation:ora-shimmer 1.4s var(--ease,ease) infinite;
}
@keyframes ora-shimmer{ from{ transform:translateX(-100%);} to{ transform:translateX(100%);} }
@media (prefers-reduced-motion:reduce){ .skel::after{ animation:none; } }

:where(.empty, .tile-empty){
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:6px; text-align:center; padding:var(--space-lg) var(--space-md);
  color:var(--text-tertiary); font-size:var(--text-sm);
}
:where(.empty) .empty-icon, :where(.tile-empty) .ic{ font-size:1.4rem; color:var(--text-tertiary); }
:where(.empty) .empty-title, :where(.tile-empty) .em-t{
  font-family:var(--font-heading); font-weight:600; color:var(--text); font-size:var(--text-md);
}

/* ---- §34 canonical slide-out ------------------------------------
   ONE overlay panel across every page: opens on row click, closes on
   the X / backdrop / Escape, right-rail width min(620px, 92vw),
   modal surface + left border + shadow. 01 (#liveSO) and 02
   (.so-backdrop/.so-panel) are native overlays; 06/09 ship an
   in-page .so-host showcase which these rules + ora-canon.js
   convert to the same overlay behaviour. */
.so-host{
  position:fixed; inset:0; height:auto; border:0; border-radius:0;
  overflow:visible; background:transparent; display:none;
  z-index:var(--z-modal, 1000);
}
.so-host.open{ display:block; }
.so-host .so-bg{
  position:absolute; inset:0; opacity:1; pointer-events:auto; padding:0;
  background:var(--surface-modal-overlay, rgba(0,0,0,.5));
}
.so-host .so-bg > *{ display:none; }
.so-host .so-panel{
  position:fixed; top:0; right:0; bottom:0;
  box-shadow:-16px 0 50px rgba(0,0,0,.45);
}
.so-panel, aside#liveSO{ width:min(620px, 92vw); }

/* §32 alignment: 04's .metric cards adopt the viz-card chrome */
:where(.metric){ border-radius:var(--radius-lg); }

/* §32 viz-switch popover (generic; 06 keeps its lock-writing .pop) */
.viz-pop{
  position:absolute; top:44px; right:var(--space-md); min-width:180px; display:none;
  background:var(--surface-raised); border:1px solid var(--border);
  border-radius:var(--radius-lg); box-shadow:var(--shadow-lg, 0 12px 40px rgba(0,0,0,.4));
  padding:var(--space-xs); z-index:var(--z-dropdown, 50);
}
.viz-pop.open{ display:block; }
.viz-pop-title{
  font-family:var(--font-mono); font-size:var(--text-2xs); letter-spacing:.1em;
  text-transform:uppercase; color:var(--text-tertiary); padding:6px 10px 8px;
}
.viz-opt{
  width:100%; display:flex; align-items:center; gap:8px; background:transparent;
  border:0; color:var(--text-secondary); padding:8px 10px; border-radius:var(--radius-md);
  font-family:var(--font-body); font-size:var(--text-sm); cursor:pointer; text-align:left;
  text-transform:capitalize;
}
.viz-opt:hover{ background:var(--glass-bg); color:var(--text); }
.viz-opt[aria-selected="true"]{ background:var(--accent-bg); color:var(--accent); }

/* ---- §35 feedback: toast + bell ping + confetti (robustness/delight) ---- */
.ora-toast-host{ position:fixed; top:64px; right:16px; z-index:calc(var(--z-modal,1000) + 5); display:flex; flex-direction:column; gap:8px; }
.ora-toast{
  background:var(--surface-raised); border:1px solid var(--border); border-left:3px solid var(--accent);
  border-radius:var(--radius-md); box-shadow:var(--shadow-lg, 0 12px 40px rgba(0,0,0,.4));
  color:var(--text); font-family:var(--font-body); font-size:var(--text-sm);
  padding:10px 14px; max-width:340px; animation:ora-toast-in .25s var(--ease,ease);
}
.ora-toast.warn{ border-left-color:var(--warn); }
.ora-toast.danger{ border-left-color:var(--danger); }
.ora-toast.win{ border-left-color:var(--ok); box-shadow:var(--shadow-glow-ok, 0 0 24px rgba(110,231,183,.18)); }
@keyframes ora-toast-in{ from{ transform:translateY(-6px); opacity:0; } to{ transform:none; opacity:1; } }
@media (prefers-reduced-motion:reduce){ .ora-toast{ animation:none; } }

.ora-notif .ora-iconbtn{ position:relative; }
.ora-notif .ora-iconbtn .ping{
  position:absolute; top:6px; right:6px; width:8px; height:8px; border-radius:50%;
  background:var(--accent); box-shadow:0 0 0 2px var(--surface, #111);
}
.ora-notif-item{
  display:flex; gap:8px; align-items:flex-start; padding:8px 10px; border-radius:var(--radius-md);
  font-size:var(--text-sm); color:var(--text-secondary);
}
.ora-notif-item .ic{ color:var(--accent); margin-top:2px; }
.ora-notif-item b{ color:var(--text); }
.ora-notif-item small{ display:block; color:var(--text-tertiary); }

.ora-confetti{ position:fixed; inset:0; pointer-events:none; z-index:calc(var(--z-modal,1000) + 10); overflow:hidden; }
.ora-confetti i{
  position:absolute; top:-12px; width:8px; height:12px; border-radius:2px; opacity:.9;
  animation:ora-confetti-fall 1.6s ease-in forwards;
}
@keyframes ora-confetti-fall{
  to{ transform:translateY(105vh) rotate(540deg); opacity:.7; }
}
@media (prefers-reduced-motion:reduce){ .ora-confetti{ display:none; } }

/* §06.6 inline capture form inside a checklist step */
.cap-form{ display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin:6px 0 8px 30px; }
.cap-form input{
  background:var(--surface-raised); border:1px solid var(--border); border-radius:var(--radius-md);
  color:var(--text); font-family:var(--font-body); font-size:var(--text-sm); padding:6px 10px; min-width:150px;
}
.cap-form input:focus{ outline:none; box-shadow:var(--focus-ring, 0 0 0 2px var(--accent)); }
.cap-form label{ font-family:var(--font-mono); font-size:var(--text-2xs); letter-spacing:.08em; text-transform:uppercase; color:var(--text-tertiary); display:flex; flex-direction:column; gap:3px; }

/* §33b skeleton settle: a skeleton that outlives its fetch becomes a quiet,
   honest placeholder instead of shimmering forever */
.skel.skel-settled{ background:var(--glass-bg); opacity:.45; }
.skel.skel-settled::after{ animation:none; content:''; }
