/* Hero panel — faithful to Sources/ImgSearch/Panel.swift + SearchView.swift.
   Sizes: idle 480, orb 64 (busyWidth = fieldHeight), slow pill ~216,
   results 700, field 64, radius 26 (32 only when square + orb-sized).
   Springs: entrance .52/.32 (width), entranceHeight .78/.44 (height),
   surface .46/.12, exit .16/0. Aura is the app's shader (app-aura.js);
   .aura-flow is the no-WebGL fallback. */
.hero .scene{container-type:inline-size}
.hero .search-panel{width:480px}
/* Idle: desktop alone, panel parked invisible before the summon. */
.search-panel[data-state="idle"]{width:480px;height:64px;border-radius:26px;opacity:0;transition:none}
/* Entrance: shell springs in from 84% on both axes — height deliberately
   out of step with width (entranceHeight vs entrance) so the shape
   undulates instead of scaling uniformly. Contents bloom at the tail. */
.search-panel[data-state="entrance"]{animation:panel-arrive-w var(--entrance) var(--arrival) both,panel-arrive-h var(--height) var(--grow) both}
.search-panel[data-state="entrance"] .search-field{animation:field-bloom var(--settle) var(--spring) .16s both}
.search-panel[data-state="typing"]{width:480px;height:64px;border-radius:26px}
.search-field{transition:opacity .2s ease-out}
/* Trailing control: crossfaded, never swapped (Motion.control). ⌥ Space when
   the query is empty, × once there is text — exactly like the app. */
.trailing-group{opacity:0;transform:scale(.7);transform-origin:right center}
.search-panel[data-state="typing"] .trailing,.search-panel[data-state="results"] .trailing{width:150px}
.search-panel[data-state="typing"] .trailing-opt,.search-panel[data-state="results"] .trailing-opt{opacity:0;transform:scale(.7)}
.search-panel[data-state="typing"] .trailing-group,.search-panel[data-state="results"] .trailing-group{opacity:1;transform:scale(1)}
/* Summoned with a standing query, the app selects it all — blue wash. */
.search-panel[data-state="results"] .query{background:rgba(62,112,255,.6);border-radius:4px;padding:0 2px}
/* Searching: contracts to a 64px glass orb. Field leaves at once (no squash),
   the aura is the indicator — the app's busy state. */
.search-panel[data-state="searching"]{width:64px;height:64px;border-radius:32px}
.search-panel[data-state="searching"] .search-field{opacity:0;transition:none}
.search-panel[data-state="searching"] .caret{display:none}
.search-panel[data-state="searching"] .aura{opacity:1}
.search-panel[data-state="searching"] .aura-flow{animation-play-state:running}
.search-panel[data-state="searching"] .results-content{opacity:0}
/* Slow search: pill around “Still searching…” (fieldPadding + label +
   fieldPadding in Typo.prominent). Aura stays lit. Corner returns to ~26:
   wide enough that squareness alone no longer rounds it into an orb. */
.search-panel[data-state="searching-slow"]{width:216px;height:64px;border-radius:26px}
.search-panel[data-state="searching-slow"] .search-field{opacity:0;transition:none}
.search-panel[data-state="searching-slow"] .aura{opacity:1}
.search-panel[data-state="searching-slow"] .aura-flow{animation-play-state:running}
.slow-label{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:15px;font-weight:500;color:#fff;white-space:nowrap;z-index:1;
  text-shadow:0 1px 3px rgba(0,0,0,.85),0 2px 6px rgba(0,0,0,.5);
  opacity:0;transition:opacity .2s ease-out;pointer-events:none;
}
.search-panel[data-state="searching-slow"] .slow-label{opacity:1}
/* Results: opens wider than idle. Divider + 34px bar + 3-col grid mirror
   SearchView.results; tiles reveal with Motion.reveal (.26s ease-out).
   Content is sized from the stage (the envelope, which never animates)
   and stays centred — the shell morphs around content that never moves,
   exactly like the app's cancelling centring terms. */
.search-panel[data-state="results"]{width:700px;height:424px;border-radius:26px}
/* Full-bleed field, like the app: destination-sized from the first frame of
   the morph (stage-based, so it never reflows mid-animation), controls hard
   against the right edge. */
.search-panel[data-state="results"] .search-field{width:min(700px,100cqw - 16px)}
/* The light stays burning behind the grid while results arrive — the app's
   thumbnail linger — spanning the whole shell (inset:0) and fading out in
   the shader when the linger timer lets go. */
.search-panel[data-state="results"] .aura{opacity:1}
.search-panel[data-state="results"] .caret{display:none}
.search-panel[data-state="results"] .slow-label{opacity:0}
.search-panel[data-state="results"] .results-content{opacity:1;transition:opacity var(--surface) ease-out .1s}
.search-panel[data-state="results"] .image-tile{opacity:1;transform:translateY(0)}
.search-panel[data-state="results"] .tile-1{transition-delay:0ms}
.search-panel[data-state="results"] .tile-2{transition-delay:40ms}
.search-panel[data-state="results"] .tile-3{transition-delay:80ms}
.search-panel[data-state="results"] .tile-4{transition-delay:120ms}
.search-panel[data-state="results"] .tile-5{transition-delay:160ms}
.search-panel[data-state="results"] .tile-6{transition-delay:200ms}
/* Exit: unified cohesive contraction toward the centre (~.94) with a brisk
   .16s ease-in fade — leaving is decisive. */
.search-panel[data-state="exit"]{width:451px;height:60px;opacity:0;transition:width var(--exit) ease-in,height var(--exit) ease-in,opacity var(--exit) ease-in}
@keyframes panel-arrive-w{from{width:403px;opacity:0}to{width:480px;opacity:1}}
@keyframes panel-arrive-h{from{height:54px}to{height:64px}}
@keyframes field-bloom{from{opacity:0;scale:.82}to{opacity:1;scale:1}}
/* Fluid widths below the fixed sizes. */
@media(prefers-reduced-motion:reduce){
  .search-panel[data-state="entrance"]{animation:none}
  .search-panel[data-state="entrance"] .search-field{animation:none}
}
