/**
 * Kåbdalis — shared block primitives + layout/animation foundations.
 *
 * Despite the filename "widget-frame.css" (kept for plugin handle compat),
 * this file is actually Claude Design's `shared/blocks.css` — the primitives
 * every widget and content block consumes.
 *
 * Contains:
 *   - .b-* primitives  : form fields (b-field/input/select/textarea/row2),
 *                        cards (b-card), kicker (b-kicker), pills (b-pill*),
 *                        chips (b-chip*)
 *   - layout primitives: .wrap, .band, .display
 *   - section helpers  : .sec-head, .sec-head--row, .eyebrow*
 *   - photo wrapper    : .photo, .photo image-slot
 *   - reveal animation : .reveal*
 *   - buttons          : .btn, .btn--primary/ghost/outline/lg
 *   - inline link arrow: .link-arrow
 *   - status dot       : .dot, .dot--on
 *
 * Loaded after tokens.css. Style overrides for theme-specific contexts
 * (e.g. .hd .btn--primary on the header) live in style.css and naturally
 * override these defaults.
 */

.b-field{ display:flex; flex-direction:column; gap:6px; }
.b-field__l{ font-family:var(--font-mono); font-size:.66rem; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-soft); }
.b-input, .b-select, .b-textarea{ width:100%; height:46px; padding:0 13px; border-radius:var(--radius-sm);
  border:1px solid var(--line); background:var(--surface); color:var(--ink); font:inherit; font-size:.94rem;
  transition:border-color .15s, box-shadow .15s; }
.b-textarea{ height:auto; min-height:92px; padding:11px 13px; line-height:1.5; resize:vertical; }
/* Select: replace the UA arrow (which hugs the far edge) with a token-colored
   chevron inset 12px, and pin color-scheme so the open option list stays light
   even under a dark OS theme (the "black dropdown" flash). Element+class
   selector deliberately outweighs plain .b-select rules elsewhere. */
select.b-select{
  -webkit-appearance:none; appearance:none;
  padding-right:38px; cursor:pointer; color-scheme:light;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23837a6b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center; background-size:16px 16px;
}
select.b-select option{ background:var(--surface); color:var(--ink); }
[data-color-scheme="dark"] select.b-select{ color-scheme:dark;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ccc4b6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); }
.b-input:focus, .b-select:focus, .b-textarea:focus{ outline:none; border-color:var(--accent);
  box-shadow:var(--focus-ring); }
/* Validation state — a field/form can add .b-field--error and render a
   .b-field__error message wired with aria-describedby for inline errors. */
.b-field--error .b-input, .b-field--error .b-select, .b-field--error .b-textarea,
.b-input[aria-invalid="true"], .b-select[aria-invalid="true"], .b-textarea[aria-invalid="true"]{
  border-color:var(--no); box-shadow:0 0 0 3px color-mix(in srgb, var(--no) 16%, transparent); }
.b-field__error{ display:flex; align-items:center; gap:6px; font-size:.78rem; font-weight:600; color:var(--no); }
.b-field__error svg{ flex:0 0 auto; }
.b-row2{ display:grid; grid-template-columns:1fr 1fr; gap:11px; }
.b-card{ background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); }
.b-kicker{ font-family:var(--eyebrow-font); text-transform:var(--eyebrow-tt); letter-spacing:var(--eyebrow-ls);
  font-weight:var(--eyebrow-w); font-size:.72rem; color:var(--accent); }
.b-pill{ display:inline-flex; align-items:center; gap:6px; height:25px; padding:0 10px; border-radius:999px; font-size:.78rem; font-weight:600; }
.b-pill--ok{ background:var(--ok-bg); color:var(--ok); }
.b-pill--no{ background:var(--no-bg); color:var(--no); }
.b-pill--warn{ background:var(--warn-bg); color:var(--warn); }
.b-pill__dot{ width:7px; height:7px; border-radius:50%; background:currentColor; }
.b-chips{ display:flex; gap:11px; flex-wrap:wrap; justify-content:center; }
.b-chip{ display:inline-flex; align-items:center; gap:8px; padding:9px 15px; border:1px solid var(--line);
  border-radius:var(--radius-sm); background:var(--surface); font-size:.9rem; }
.b-chip svg{ color:var(--accent); }

.wrap{ width:100%; max-width:var(--maxw); margin:0 auto; padding-inline:clamp(18px,5vw,40px); }
.band{ padding-block:var(--band-pad); }
.display{ font-family:var(--font-display); font-weight:var(--display-w); letter-spacing:var(--display-ls); line-height:var(--display-lh); }

.eyebrow{ font-family:var(--eyebrow-font); text-transform:var(--eyebrow-tt);
  letter-spacing:var(--eyebrow-ls); font-weight:var(--eyebrow-w);
  font-size:.72rem; color:var(--accent); display:inline-flex; align-items:center; gap:.5em; }
.eyebrow--light{ color:rgba(255,255,255,.92); }

.reveal{ transition:opacity .55s ease, transform .62s cubic-bezier(.22,.68,.3,1); transition-delay:var(--d,0ms); }
.reveal.armed{ opacity:0; transform:translateY(20px); }
.reveal.in{ opacity:1; transform:none; }
@media (prefers-reduced-motion: reduce){
  .reveal, .reveal.armed{ opacity:1; transform:none; transition:none; }
}

.photo{ width:100%; overflow:hidden; border-radius:var(--radius); background:var(--surface2); }
.photo image-slot{ border-radius:inherit; }
.photo img{ transition:transform .6s var(--ease-out); }

.btn{ display:inline-flex; align-items:center; gap:.55em; font-weight:600; font-size:.95rem;
  padding:.82em 1.25em; border-radius:999px; line-height:1; transition:transform .16s ease, filter .2s ease, background .2s ease, border-color .2s ease, color .2s ease; white-space:nowrap; }
.btn svg{ transition:transform .2s ease; }
.btn:hover svg{ transform:translateX(3px); }
.btn:active{ transform:scale(.96); }
.btn--primary{ background:var(--accent); color:var(--on-accent); }
.btn--primary:hover{ filter:brightness(1.06); }
/* Ghost button — inherits color from its container so it works on both
   dark photo backgrounds (where parent color is white) and light surface
   cards (where parent color is var(--ink)). Avoid hardcoding #fff here. */
.btn--ghost{ background:color-mix(in srgb, currentColor 12%, transparent); color:inherit; border:1.5px solid color-mix(in srgb, currentColor 55%, transparent); backdrop-filter:blur(4px); }
.btn--ghost:hover{ background:color-mix(in srgb, currentColor 22%, transparent); }
.btn--outline{ border:1.5px solid var(--ink); color:var(--ink); }
.btn--outline:hover{ background:var(--ink); color:var(--bg); }
.btn--lg{ padding:1em 1.5em; font-size:1.02rem; }
.btn--sm{ padding:.55em .9em; font-size:.86rem; gap:.4em; }

.link-arrow{ display:inline-flex; align-items:center; gap:.5em; font-weight:600; color:var(--accent);
  border-bottom:1.5px solid transparent; padding-bottom:2px; transition:border-color .2s, gap .2s; }
.link-arrow:hover{ border-color:var(--accent); gap:.8em; }
.link-arrow svg{ transition:transform .2s; }
.link-arrow:hover svg{ transform:translateX(3px); }
.link-arrow:active, .evcard__more:active{ transform:translateY(1px); }

.sec-head{ margin-bottom:clamp(24px,4vw,40px); }
.sec-head h2{ font-size:clamp(1.7rem,5.5vw,2.6rem); margin:.32em 0 0; }
.sec-head--row{ display:flex; align-items:flex-end; justify-content:space-between; gap:16px; flex-wrap:wrap; }
.sec-head--row > div{ min-width:0; }
.intro .eyebrow::before, .feature__body .eyebrow::before, .sec-head .eyebrow::before, .news__text .eyebrow::before{
  content:''; width:26px; height:1.5px; background:var(--accent); border-radius:2px; opacity:.85; }

.dot{ width:9px; height:9px; border-radius:50%; background:var(--muted); }
.dot--on{ background:var(--live); box-shadow:0 0 0 3px color-mix(in srgb, var(--live) 22%, transparent); }

@media (max-width:600px){
  .sec-head--row{ align-items:flex-start; }
}

/* ---------- reveal-on-view (.rv) and image-curtain (.irv) ----------
   Theme-owned entry-animation primitives. Adds `.rv` (text/element fade+lift)
   or `.irv` (image curtain) to any element, with optional `--d` stagger.
   theme.js runs ONE shared IntersectionObserver that toggles `.in` once per
   element and unobserves — cost is O(elements) on first paint, zero
   afterwards. Honours prefers-reduced-motion globally.

   This file is enqueued in BOTH the editor iframe (via the plugin's
   `enqueue_block_assets` path in kabdalis-blocks-2.php) and on the
   frontend (via `@import` from style.css), so editor previews see the
   same reveal animation as visitors do.

   Server-side, the plugin's `kabdalis_blocks_2_inject_reveal` filter adds
   `.rv` to every kabdalis-blocks-2 block's outer wrapper automatically
   (with a small denylist of self-animating / immediately-visible blocks).
   For per-element staggers, blocks add `.rv` to inner nodes directly in
   their save() output — see intro-story / feature-split / family-story. */
.rv{ opacity:0; transform:translateY(22px); will-change:opacity,transform; }
.rv.in{
  opacity:1; transform:none;
  transition:opacity .8s var(--ease), transform .8s var(--ease);
  transition-delay:var(--d,0ms);
  will-change:auto;
}
@media (prefers-reduced-motion: no-preference){
  .irv{
    clip-path:inset(7% 7% 7% 7%); transform:scale(1.06);
    transition:clip-path 1.1s var(--ease), transform 1.3s var(--ease);
    transition-delay:var(--d,0ms);
    will-change:clip-path,transform;
  }
  .irv.in{ clip-path:inset(0 0 0 0); transform:none; will-change:auto; }
}
@media (prefers-reduced-motion: reduce){
  .rv{ opacity:1; transform:none; }
}

/* Editor canvas neutraliser — theme.js's IntersectionObserver doesn't run in
   wp-admin, so without this `.rv` elements would stay at opacity:0 in the
   editor preview. These selectors only exist inside the block editor, so
   they're inert on the frontend. */
.editor-styles-wrapper .rv,
.editor-styles-wrapper .irv,
.block-editor-block-list__layout .rv,
.block-editor-block-list__layout .irv,
.is-root-container .rv,
.is-root-container .irv{
  opacity:1 !important; transform:none !important; clip-path:none !important;
}

/* ---------- .b-spin : reusable loading spinner ----------
   Replaces the per-widget @keyframes spin copies (price-table, booking-modal,
   pist-map, …). Sizes to the surrounding font (em) and inherits colour via
   currentColor, so a block just sets `color` to tint it. Loaded site-wide via
   widget-frame, so every block + theme surface can use it. */
.b-spin{ display:inline-block; width:1.1em; height:1.1em; vertical-align:-.15em;
  border:2px solid color-mix(in srgb, currentColor 22%, transparent); border-top-color:currentColor;
  border-radius:50%; animation:b-spin .8s linear infinite; }
@keyframes b-spin{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion: reduce){ .b-spin{ animation-duration:1.6s; } }

/* ---------- .b-skeleton : reusable loading placeholder ----------
   A shimmering block a data widget (snow report, lifts, forecast, …) can render
   while its view.js fetches, so the first paint is a shaped placeholder instead
   of an empty box. The caller sets width/height (and optionally border-radius);
   honours reduced-motion with a static tint. Loaded site-wide via widget-frame,
   so any block + theme surface can use it. Pair with .b-spin for inline spinners. */
.b-skeleton{ position:relative; overflow:hidden;
  background:color-mix(in srgb, var(--ink) 7%, var(--surface2)); border-radius:var(--radius-sm); }
.b-skeleton::after{ content:''; position:absolute; inset:0;
  background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--surface) 72%, transparent), transparent);
  transform:translateX(-100%); animation:b-skeleton 1.4s ease-in-out infinite; }
@keyframes b-skeleton{ to{ transform:translateX(100%); } }
@media (prefers-reduced-motion: reduce){ .b-skeleton::after{ animation:none; } }

/* ---------- .b-error : data-widget failure state ----------
   A compact "couldn't load" panel + retry button a live widget can render when
   a fetch fails, instead of collapsing to an empty box. The widget wires the
   retry click; markup convention:
     <div class="b-error"><span class="b-error__msg">…</span>
       <button class="b-error__retry">Försök igen</button></div> */
.b-error{ display:flex; flex-direction:column; align-items:flex-start; gap:10px; padding:16px 18px;
  border:1px solid var(--line); border-radius:var(--radius); background:var(--surface);
  color:var(--ink-soft); font-size:.92rem; }
.b-error__msg{ display:flex; align-items:center; gap:9px; }
.b-error__msg svg{ color:var(--no); flex:0 0 auto; }
.b-error__retry{ display:inline-flex; align-items:center; gap:.5em; font-weight:600; font-size:.88rem;
  padding:.5em 1em; border-radius:999px; border:1.5px solid var(--line); background:transparent; color:var(--ink);
  cursor:pointer; transition:background .15s ease, border-color .15s ease, color .15s ease; }
.b-error__retry:hover{ border-color:var(--accent); color:var(--accent); }
[data-dir="minimal"] .b-error__retry{ border-radius:2px; }

/* ---------- freshness: stale "last updated" label (toggled by theme.js
   relativeTime() on [data-kab-updated] elements that pass data-kab-stale-mins) ---------- */
.is-stale{ color:var(--warn); }
.is-stale::after{ content:''; display:inline-block; width:6px; height:6px; margin-inline-start:6px;
  border-radius:50%; background:var(--warn); vertical-align:middle; }
