/* --- Palette -------------------------------------------------------------
   Taken from the logo, not invented: the mark is a single flat blue, sampled
   at #306D9D. Everything here is built around that one colour, so the site and
   the logo read as the same object.

   Nothing green. The earlier draft used an Adriatic teal, which is a defensible
   colour for a campsite on this coast but reads as green next to the mark and
   made the logo look like it had wandered in from somewhere else.

   The neutrals are pulled a few degrees toward the same blue rather than being
   pure grey, which is what keeps the greys and the brand looking chosen
   together instead of merely coexisting.
   ------------------------------------------------------------------------- */
:root {
    --brand:          #306D9D;
    --brand-dark:     #24547A;
    --brand-deep:     #1B3F5C;

    /* The one warm note on the site, used ONLY on the primary action and the
       eyebrow rule. A single accent against a monochrome blue page is what
       makes a call to action findable; spending it anywhere else would undo
       that. Sampled to sit at equal weight against #306D9D. */
    --accent:         #C2571B;
    --accent-dark:    #9B4413;

    /* Light theme.

       Not white. #FFFFFF next to the navy hero read as two unrelated surfaces
       stuck together, and it is the wrong ground for a site about the sea. The
       page carries a few degrees of the brand's own hue instead -- enough to
       feel tinted rather than grey, little enough that text contrast is
       untouched (#12212E on #F4F8FB is 14.9:1, well past AAA).

       The three stay a clear step apart, because the whole layout depends on
       .alt sections and cards reading as distinct planes: page, alternate band,
       sunken. Cards go slightly LIGHTER than the page rather than white-on-grey,
       which is what keeps them lifting off it. */
    --bg:             #F4F8FB;
    --bg-alt:         #E8F0F6;
    /* The sticky header sits a shade below the page so it reads as its own
       plane rather than as the page that forgot to scroll. Deliberately NOT
       --bg-alt: matching that would make the bar look like an alternate
       section pinned to the top.

       It carries noticeably more of the brand hue than the page does. At
       #EBF2F8 it was a barely-tinted grey, and against the photographs in the
       band directly below it read as an off-white strip that had wandered in.

       The value has to be read together with the 88% color-mix below: scrolled,
       the bar borrows the dark page content passing under it and looks blue for
       free, but sitting at the top of the page it is mixed with #F4F8FB, which
       is the one place the tint gets washed out and therefore the place the
       colour has to be chosen for. At the top it composites to #CDE0F1.
       Contrast is untouched -- #12212E on that is 12:1. */
    --header-bg:      #C8DDF0;
    /* Flat white, not --card-bg's #FDFEFF: the current-page chip is a small
       shape on a saturated bar and it wants the full step. 16.9:1 under the
       body text sitting in it. */
    --nav-current-bg: #FFFFFF;
    /* The footer sits on --bg-sunken, not on the header's colour, so the
       current-page chip needs its own value to keep the same one-step lift. */
    --foot-current-bg: #FFFFFF;
    --foot-hover-bg:   #E9F1F8;
    /* The orange of the bottom line. It cannot be one value: that line sits
       on --bg-sunken, which is a light blue-grey here and a dark navy in the
       other theme, so a readable orange has to be dark in one and light in
       the other. #E36C0A -- the eyebrow's -- reads 2.58:1 on this ground.
       This one is 4.57:1, and the dark theme's is 4.94:1. */
    --foot-accent:     #A8490A;
    --bg-sunken:      #DAE6EF;
    --text:           #12212E;
    --text-muted:     #4C5F72;
    --border:         #C3D4E2;
    --card-bg:        #FDFEFF;
    --card-shadow:    0 1px 2px rgba(18, 33, 46, .05), 0 8px 24px rgba(18, 33, 46, .07);
    --card-shadow-hi: 0 2px 4px rgba(18, 33, 46, .08), 0 16px 40px rgba(18, 33, 46, .13);

    /* Hero band -- deep navy in both themes, the logo's own backdrop. */
    --hero-top:       #1B3F5C;
    --hero-bottom:    #0D2233;
    --hero-text:      #FFFFFF;
    /* Lifted from #A9C4D8 when the photographs went in behind the band. The
       old value was a comfortable muted blue against flat navy and 3.4:1
       against navy laid over a bright sky, which is a fail; this one holds
       5.7:1 there and still sits a clear step under the white heading. */
    --hero-muted:     #C6DAEA;

    --radius:         14px;
    --radius-sm:      10px;
    --wrap:           1120px;

    --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial,
            "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
    --font-mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "SF Mono", Menlo, Consolas, monospace;

    color-scheme: light;
}

/* --- Dark theme ----------------------------------------------------------
   js/theme.js stamps data-theme on <html> before first paint, so the ATTRIBUTE
   is what normally applies. The media query is the no-JS fallback and is
   written to lose against an explicit light choice.

   #306D9D is too dark to carry text on a navy ground, so the brand lightens
   here rather than being used flat. The logo gets the same treatment through a
   filter on .brand-mark below -- one mark, two grounds.
   ------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --bg:             #0B1926;
        --header-bg:      #071220;
        --nav-current-bg: #1D3B55;
        --foot-current-bg: #26496A;
        --foot-hover-bg:   #1F3E59;
        --foot-accent:     #F0803C;
        --bg-alt:         #11253600;
        --bg-alt:         #112536;
        --bg-sunken:      #17324A;
        --text:           #E4EDF5;
        --text-muted:     #A2B8CC;
        --border:         #244159;
        --card-bg:        #112536;
        --card-shadow:    0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.25);
        --card-shadow-hi: 0 2px 4px rgba(0,0,0,.35), 0 16px 40px rgba(0,0,0,.4);
        --brand:          #6BA8D8;
        --brand-dark:     #93C2E6;
        --accent:         #F0803C;
        --accent-dark:    #FF9E66;
        color-scheme: dark;
    }
}

:root[data-theme="dark"] {
    --bg:             #0B1926;
    --header-bg:      #071220;
    --nav-current-bg: #1D3B55;
    --foot-current-bg: #26496A;
    --foot-hover-bg:   #1F3E59;
    --foot-accent:     #F0803C;
    --bg-alt:         #112536;
    --bg-sunken:      #17324A;
    --text:           #E4EDF5;
    --text-muted:     #A2B8CC;
    --border:         #244159;
    --card-bg:        #112536;
    --card-shadow:    0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.25);
    --card-shadow-hi: 0 2px 4px rgba(0,0,0,.35), 0 16px 40px rgba(0,0,0,.4);
    --brand:          #6BA8D8;
    --brand-dark:     #93C2E6;
    --accent:         #F0803C;
    --accent-dark:    #FF9E66;
    color-scheme: dark;
}

/* --- Base ---------------------------------------------------------------- */

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

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font);
    font-size: 17px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }

a { color: var(--brand); text-underline-offset: 2px; }
a:hover { color: var(--brand-dark); }

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

h1, h2, h3 { line-height: 1.15; text-wrap: balance; margin: 0; letter-spacing: -.02em; }
h1 { font-size: clamp(34px, 5.5vw, 52px); font-weight: 800; }
h2 { font-size: clamp(26px, 3.4vw, 36px); font-weight: 700; }
h3 { font-size: 20px; font-weight: 650; letter-spacing: -.01em; }

p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }

.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
    position: absolute; left: -9999px; top: 0; z-index: 100;
    background: var(--accent); color: #fff; padding: 12px 18px; border-radius: 0 0 var(--radius-sm) 0;
}
.skip:focus { left: 0; }

/* --- Header -------------------------------------------------------------- */

.site-header {
    position: sticky; top: 0; z-index: 50;
    background: color-mix(in srgb, var(--header-bg) 88%, transparent);
    backdrop-filter: saturate(140%) blur(10px);
    border-bottom: 1px solid var(--border);
}

.header-inner { display: flex; align-items: center; gap: 16px; min-height: 66px; }

/* Centred on the mark. The wordmark's optical centre lines up with the middle
   of the roundel, which is what makes the two read as one lockup now that the
   mark is square -- it was bottom-aligned while the mark still carried the
   vertical lettering and stood twice the wordmark's height. */
.brand {
    display: flex; align-items: center; gap: 12px;
    font-weight: 800; font-size: 19px; letter-spacing: -.02em;
    color: var(--text); text-decoration: none; white-space: nowrap;
}
/* The wordmark is a very wide artwork (7936x850 after cropping its empty
   margins away -- it carried 50% dead space vertically and 20% horizontally),
   so it is sized by height and left to find its own width. Capping max-width as
   well stops it pushing the nav off the row on a narrow laptop. */
.brand-word { height: 19px; width: auto; max-width: 42vw; flex: none; }
@media (max-width: 420px) { .brand-mark { height: 46px; } .brand-word { height: 16px; } }

/* The mark is a single flat #306D9D with transparency, so it sits on the light
   ground as drawn. On the navy ground that blue goes muddy, so it is lightened
   to match --brand's dark-theme value rather than being swapped for a second
   image file. */
.brand-mark { height: 56px; width: auto; flex: none; }
:root[data-theme="dark"] .brand-mark,
:root[data-theme="dark"] .brand-word { filter: brightness(1.55) saturate(.9); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .brand-mark,
    :root:not([data-theme="light"]) .brand-word { filter: brightness(1.55) saturate(.9); }
}

.header-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }

.site-nav ul { display: flex; gap: 4px; list-style: none; margin: 0; padding: 0; }
/* Every item the same height, so the current-page chip is the same shape
   whichever page you are on. The Windsurfing entry is a three-line lockup and
   the rest are one line; with vertical padding doing the sizing, its chip came
   out 4px taller than everybody else's. min-height sizes them all instead, and
   flex centring keeps one line and three lines on the same axis. */
.site-nav a {
    display: flex; align-items: center; min-height: 45px;
    padding: 0 12px; border-radius: var(--radius-sm);
    color: var(--text-muted); text-decoration: none; font-size: 15px; font-weight: 550;
    /* A label that wraps turns one bar row into two. Polish "Pytania i
       regulamin" was doing exactly that just above the collapse point. */
    white-space: nowrap;
}
.site-nav a:hover { color: var(--text); background: var(--bg-alt); }
/* The page you are on lifts OFF the bar rather than sinking into it. It used to
   be --bg-sunken, which was a step down from a near-white header and read
   correctly then; against the blue bar the header now carries, a step down is a
   step toward the bar's own colour and the marker went quiet. */
.site-nav a[aria-current="page"] { color: var(--text); background: var(--nav-current-bg); }

/* --- the lockup as a menu item --------------------------------------------
   The Windsurfing entry is the page's own heading in miniature: Wind / Kite /
   Wing stacked right-aligned against one shared ending.

   The proportion is NOT the hero's. There the stack is .34 of the big word,
   which at 52px leaves it at 18px -- comfortably readable. Hold that ratio at a
   15px menu and the stack lands at 5px, which is a texture and not three words.
   So the small half is set in absolute px and pushed as large as the row can
   carry: 9px against the 15px ending, a ratio of .6.

   Three 9px lines at 1.06 come to 29px, which with the link's own padding puts
   the item at 45px inside a 66px bar -- taller than its neighbours, still well
   inside the row, and it is what makes the menu and the page agree. */
/* display: flex, not inline-flex. Inline, the link's own 15px line box adds a
   strut under a 29px lockup and the item came out 54.6px tall in a 66px bar. */
.navlock { display: flex; align-items: center; gap: 3px; }
/* No font-weight on either half. The hero lockup inherits the h1's 800 and this
   one inherits its link's, which is 550 in the header bar and 400 in the footer
   list -- set it to 700 and the item reads as bold against its own neighbours,
   which is the one thing a menu item must not do. */
.navlock-stack {
    display: flex; flex-direction: column; text-align: right;
    font-size: 9px; line-height: 1.06; letter-spacing: .01em;
}
.navlock-word { font-size: 15px; line-height: 1; }

/* The Viganj row: the village over the peninsula it sits on. Not the lockup's
   proportion -- there is no shared ending here to set one name small against,
   so both stay at the row's own size and only the leading tightens. Two 15px
   lines at 1.12 come to 34px, which still sits inside the 45px row the other
   items set, so the bar does not grow a millimetre for it. */
/* Centred on each other rather than flush left: Viganj is the shorter word
   and hanging it off the same left edge as Pelješac reads as a list of two
   things, not as one place named twice. */
.navstack { display: flex; flex-direction: column; align-items: center; line-height: 1.12; }
/* Centred in the header bar, where each item is its own island and the two
   words read as one label. Flush left in the footer list, where they sit in a
   column of other links and every one of those starts at the same x -- centring
   them there breaks the edge the eye is following down the list. */
.footer-site .navstack { align-items: flex-start; }
/* And the lockup with them. Its three beginnings are right-aligned everywhere
   else, because that is what butts them against the shared ending and makes the
   join read as one word. In a column of links that costs the left edge, so here
   the rag moves to the other side: the join opens by about 5px at 9px type,
   which is less wrong than three words that start nowhere in particular. */
.footer-site .navlock-stack { text-align: left; }
/* The hero's -.105em over-corrects here. The stack's ink-vs-box error scales
   with the STACK's size and the descender's with the WORD's, and the two are
   in a different ratio at 9/15 than at 18/52. Measured: -.033em. */
.navlock-tail { position: relative; top: -.033em; }

.nav-toggle { display: none; }

.icon-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; padding: 0;
    background: transparent; border: 1px solid var(--border); border-radius: var(--radius-sm);
    color: var(--text); cursor: pointer;
}
.icon-btn:hover { background: var(--bg-alt); }
.icon-btn svg { width: 18px; height: 18px; }

/* Language picker */
.lang { position: relative; }
.lang-menu {
    position: absolute; right: 0; top: calc(100% + 8px); min-width: 170px;
    background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
    box-shadow: var(--card-shadow-hi); padding: 6px; display: none; z-index: 60;
}
.lang-menu[data-open="true"] { display: block; }
.lang-menu a {
    display: flex; align-items: center; padding: 8px 12px; border-radius: 8px;
    color: var(--text); text-decoration: none; font-size: 15px;
}
.lang-menu a:hover { background: var(--bg-alt); }
.lang-menu a.is-current { color: var(--brand); font-weight: 650; }

/* Flags, same treatment as avento.hr: a background image on a fixed 20x15 box
   rather than an <img>, so the row height never depends on the artwork and a
   flag that fails to load leaves a neutral chip instead of a broken icon.

   The hairline ring is what keeps the white in the Croatian and Czech flags
   from bleeding into a light card, and the Slovenian from disappearing into
   it entirely. */
.flag {
    display: inline-block; width: 20px; height: 15px; margin-right: 10px;
    vertical-align: middle; flex: none;
    background-repeat: no-repeat; background-position: center; background-size: cover;
    border-radius: 2px; box-shadow: 0 0 0 1px rgba(0, 0, 0, .12);
}
.flag-us { background-image: url(../img/flags/us.svg); }
.flag-de { background-image: url(../img/flags/de.svg); }
.flag-hr { background-image: url(../img/flags/hr.svg); }
.flag-si { background-image: url(../img/flags/si.svg); }
.flag-cz { background-image: url(../img/flags/cz.svg); }
.flag-pl { background-image: url(../img/flags/pl.svg); }
.flag-fr { background-image: url(../img/flags/fr.svg); }
.flag-it { background-image: url(../img/flags/it.svg); }
.flag-es { background-image: url(../img/flags/es.svg); }

/* In the trigger the flag stands alone, so it carries no gap. */
.icon-btn .flag { margin-right: 0; }

/* --- Hero ---------------------------------------------------------------- */

.hero {
    position: relative;
    /* Own stacking context, so the negative-z photo and tint below stay inside
       the band instead of sliding behind the page. */
    isolation: isolate;
    overflow: hidden;
    /* Still the flat navy gradient. It is what shows before the first photo
       decodes, what shows if the images 404, and what fills the band on the
       slowest connection -- the hero is never empty. */
    background: linear-gradient(165deg, var(--hero-top), var(--hero-bottom));
    color: var(--hero-text);
    padding: clamp(56px, 9vw, 104px) 0;
}

/* --- Hero photographs -----------------------------------------------------
   The old WordPress site ran a full-bleed slideshow behind everything; this is
   the same eight pictures, confined to the hero band. Painting order does the
   work: negative z-index children draw ON TOP of the section's own background
   but UNDER its in-flow content, so photo, tint and text stack without any of
   them needing a positive z-index that could fight the sticky header.
   ------------------------------------------------------------------------- */

.hero-media { position: absolute; inset: 0; z-index: -2; }

.hero-slide {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover; object-position: center;
    opacity: 0;
    transition: opacity 1.6s ease-in-out;
}
.hero-slide.is-on { opacity: 1; }

/* The tint, and over it the mesh.

   The mesh is the old theme's own grid.png -- the same 8px tile, the same
   alphas, recoloured from near-black to the brand blue. It is what keeps a
   photograph from looking like a photograph someone dropped behind the text:
   it screens the picture back into the same material as the rest of the page.

   The tint is set at .80 wherever text sits, and that number is not a taste
   call: .80 is the lightest the navy can go while every colour the hero prints
   still clears WCAG AA against the WORST case a photograph can present, which
   is a blown-out white sky under the lightest pixel of the mesh. There, white
   heading is 8.1:1, the lede 5.7:1, the eyebrow 4.9:1. Push it to .70 and the
   lede falls to 3.4:1 -- readable on the pictures with pines in them, not on
   the ones with sky, and a hero that is legible on five slides out of eight is
   not legible.

   Narrow screens get the same .80 evenly. They have no spare column to hand the
   photograph, so the alternative is a band that goes black on a phone, which is
   the whole point of putting pictures there undone. */
.hero::after {
    content: "";
    position: absolute; inset: 0; z-index: -1;
    pointer-events: none;
    background:
        url(../img/hero-grid.png) repeat,
        linear-gradient(165deg, rgba(13, 34, 51, .80), rgba(9, 24, 38, .86));
}

/* Wide enough for a text column AND something else. Only here does the tint
   fall away on the right, down to .30, where the photograph gets to be a
   photograph rather than a texture.

   1150px, not 820px, and the breakpoint is the whole argument: the wrap caps at
   1120px, so below about 1150 the heading and lede run nearly the full width of
   the band and there is no "right" to give away -- opening it up there would
   drop the last third of every line onto a .5 scrim. Above it the wrap centres
   and the text ends around the middle, which is exactly where the plateau does.
   The measured lede in this layout never sees less than .78. */
@media (min-width: 1150px) {
    .hero::after {
        background:
            url(../img/hero-grid.png) repeat,
            linear-gradient(100deg,
                rgba(11, 28, 43, .86) 0%,
                rgba(13, 34, 51, .80) 54%,
                rgba(20, 52, 78, .44) 82%,
                rgba(24, 60, 90, .30) 100%);
    }
}

/* A slideshow that fades on its own is motion the visitor did not ask for.
   js/maestral.js does not start it at all under reduce; killing the transition
   here as well covers the class being toggled by anything else. */
@media (prefers-reduced-motion: reduce) {
    .hero-slide { transition: none; }
}

.hero .wrap { position: relative; }

/* --- wind / kite / wing lockup --------------------------------------------
   The Windsurfing page heading is one word with three beginnings: the three
   prefixes stack in a small column, right-aligned so they all butt up against
   the shared ending, which stays at full heading size beside them.

   Everything is in em, so the whole lockup rides the h1's own clamp() and
   scales with the viewport rather than needing its own breakpoints. The stack
   is .34em, which puts three of its lines at almost exactly the cap height of
   one line of the big word -- that match is what makes the two halves read as
   a single object instead of a heading with a list glued to it.

   It is aria-hidden and followed by an sr-only sentence: read aloud, "wind kite
   wing surfing" is not a heading, it is a word search. */
.lockup { display: flex; align-items: center; gap: .18em; }
.lockup-stack {
    display: flex; flex-direction: column; text-align: right;
    font-size: .34em; line-height: 1.16; letter-spacing: 0;
}
/* line-height 1 on the big word, so its box hugs its own ascender and descender.
   With the h1's 1.15 the box carries half a line of air that belongs to nobody,
   and align-items: center then centres THAT -- which puts the letters visibly
   high against the three stacked lines even though the boxes are level. */
.lockup-word { line-height: 1; }
/* Optical centring, and the reason it needs a class rather than a constant.

   align-items: center lines up the two BOXES, and the boxes lie: wind/kite/wing
   have no descender at all, so the stack's ink sits high inside its own box,
   while a word ending in -ing hangs a g below its baseline and sits low in its.
   Centred boxes therefore read as a word sitting too low against the three.

   Measured against the stack's ink centre, the error is -0.105em for "surfing"
   and +0.010em -- half a pixel, nothing -- for "surfen" and "surf". So the
   correction belongs on the suffixes that have a tail, which is exactly the
   five languages that end the word in -ing. top rather than transform, because
   a transformed text layer resamples and this is 52px of display type. */
.lockup-tail { position: relative; top: -.105em; }
.hero h1 { color: var(--hero-text); max-width: 18ch; }
.hero .lede { color: var(--hero-muted); font-size: clamp(18px, 2.2vw, 21px); max-width: 56ch; margin-top: 18px; }
/* NOT --accent. That burnt orange was chosen against a light page; over the
   photograph it reads 1.7:1, which is a decoration rather than a word. This is
   the same hue carried up to where 12px can be read on it: 4.9:1. */
/* Set the way avento.hr sets its own eyebrow -- the body sans at 700, .76rem,
   .13em -- rather than in the mono face. Two sites by the same hand, and the
   label above the heading is the one piece of typography they now share.

   The colour comes across with it: #E36C0A, avento.hr's own brand orange, not
   this site's --accent. Worth knowing what that costs. The eyebrow sits at the
   top left of the band, on the .86 stop, which is the darkest ground the hero
   has; against a blown-out sky there it reads 3.24:1 and on a typical slide
   4.08:1. At 12.16px that is under AA either way -- #FF9440 is the same orange
   a step lighter and clears it at 4.83:1 -- and matching Avento was the point,
   so the brand value stands. */
.hero .eyebrow {
    font-size: .76rem; font-weight: 700; letter-spacing: .13em;
    text-transform: uppercase; color: #E36C0A; margin-bottom: 14px;
}

.cta-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }
/* A CTA row that closes a long price table rather than a short block of copy. */
.cta-row-loose { margin-top: 36px; }

.btn {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 12px 22px; border-radius: var(--radius-sm);
    font-weight: 650; font-size: 16px; text-decoration: none; border: 1px solid transparent;
    cursor: pointer;
}
.btn-primary { background: var(--brand); color: #fff; }
/* Icons in buttons (the contact form's paper-plane Send): sized here, the CSP blocks style attributes. */
.btn svg { width: 18px; height: 18px; flex: none; }
.btn-primary:hover { background: var(--brand-dark); color: #fff; }
/* On the navy hero the brand blue sits too close to the band behind it, so the
   primary button lightens there instead of relying on contrast it does not have. */
.hero .btn-primary { background: #4A8CC2; }
.hero .btn-primary:hover { background: #63A2D6; }
:root[data-theme="dark"] .btn-primary { color: #08131C; }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .btn-primary { color: #08131C; }
}
.btn-ghost { border-color: rgba(255,255,255,.3); color: #fff; }
.btn-ghost:hover { background: rgba(255,255,255,.1); color: #fff; }
.btn-outline { border-color: var(--border); color: var(--text); }
.btn-outline:hover { background: var(--bg-alt); color: var(--text); }

/* --- Sections ------------------------------------------------------------ */

section { padding: clamp(48px, 7vw, 80px) 0; }
section.alt { background: var(--bg-alt); }

.section-head { max-width: 62ch; margin-bottom: 36px; }
.section-head p { color: var(--text-muted); font-size: 18px; margin-top: 12px; }
/* A heading that opens a SECOND topic inside one section (Extras, What to put in the
   email) needs air above it; one class instead of eighteen inline styles. */
.section-head.gap { margin-top: 72px; }

.prose { max-width: 68ch; }
/* Standalone explanatory paragraphs that follow a section's own copy (how the wind behaves, what
   the bill is made of, the good-faith note under the prices). These carried style attributes until
   the site's CSP -- style-src 'self', no 'unsafe-inline' -- meant the browser dropped every one of
   them: same reasoning as .section-head.gap above, one class instead of nine copies per rule. */
.note { max-width: 68ch; color: var(--text-muted); margin-top: 20px; }
.note-tight { margin-top: 16px; }
.note-fine { margin-top: 24px; font-size: 15px; }
/* h2 carried margin: 0 from the heading reset while p has no top margin, so a
   heading in prose sat flush on its own first line. h3 below had already been
   given a bottom margin; h2 was simply missed. */
.prose h2 { margin-top: 2.2rem; margin-bottom: .55rem; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: 1.8rem; margin-bottom: .4rem; }
.prose ul { padding-left: 22px; }
.prose li { margin-bottom: .4rem; }

.grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

.card {
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 24px; box-shadow: var(--card-shadow);
}
.card h3 { margin-bottom: 8px; }
.card p { color: var(--text-muted); font-size: 16px; }
.card .ico { color: var(--accent); margin-bottom: 14px; }
.card .ico svg { width: 26px; height: 26px; }

/* --- The village schools (windsurfing page) -------------------------------
   Cards with a photograph running to their own edge, so the padding lives on the
   text half rather than on .card itself. Each tile IS the link -- one target, one
   tab stop -- which is why everything inside is a span: an <a> may not contain
   block-level children. */
.schools { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); margin-top: 26px; }
.schools .card { display: block; padding: 0; overflow: hidden; color: inherit; text-decoration: none; }
.school-photo { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.school-text { display: block; padding: 18px 20px 20px; }
.school-name { display: block; font-weight: 650; font-size: 17px; }
.school-meta { display: block; color: var(--text-muted); font-size: 15px; margin-top: 4px; }
/* The distance is a fact about US, not about them, so it gets its own row rather than
   riding the sports line -- and the mono face is the one the .facts rows already use for
   a measured value. */
.school-dist { display: block; color: var(--text-muted); font-family: var(--font-mono); font-size: 13px; margin-top: 6px; }
/* The cue is the only part that looks like a link, and it carries the arrow that
   says the tile leaves the site. */
.school-cue { display: block; color: var(--brand); font-size: 15px; font-weight: 550; margin-top: 12px; }
/* VS15 after the arrow: without it Chrome picks the emoji face, which lands as a
   blue-on-blue tile rather than as a glyph in the link's colour. */
.school-cue::after { content: " \2197\FE0E"; }
.schools .card:hover { border-color: var(--brand); box-shadow: var(--card-shadow-hi); }
.schools .card:hover .school-cue { text-decoration: underline; }

/* Fact list — the "what you get" rows */
.facts { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--card-bg); }
/* Dense rows, like the price table beside them: these are scanned, not read. */
.facts div { display: grid; grid-template-columns: 210px 1fr; gap: 16px; padding: 7px 18px; border-bottom: 1px solid var(--border); line-height: 1.4; }
.facts div:last-child { border-bottom: none; }
.facts dt, .facts .k {
    font-family: var(--font-mono); font-size: 12px; letter-spacing: .07em;
    text-transform: uppercase; color: var(--text-muted); padding-top: 3px;
}
.facts .v { color: var(--text); }

/* --- Tables (price list) ------------------------------------------------- */

.table-scroll { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card-bg); }
table { border-collapse: collapse; width: 100%; min-width: 460px; font-size: 15px; }
caption { text-align: left; padding: 14px 18px 0; font-weight: 650; }
/* Dense rows: a price list is scanned, not read, and the season columns should stay on one
   screen. The 24px icon plate in the live table sets the row height, not the padding. */
th, td { padding: 6px 18px; text-align: left; border-bottom: 1px solid var(--border); line-height: 1.35; }
th {
    font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .08em;
    text-transform: uppercase; color: var(--text-muted); font-weight: 600; white-space: nowrap;
}
td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Date-range column headers sit right-aligned OVER the prices they govern, in the accent
   orange -- they are the season picker of the table, not furniture. */
th.num { text-align: right; color: var(--accent); }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--bg-alt); }
.free { color: var(--brand); font-weight: 650; }

/* --- FAQ ----------------------------------------------------------------- */

details {
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--card-bg); margin-bottom: 10px; padding: 0;
}
summary {
    cursor: pointer; padding: 15px 20px; font-weight: 600; list-style: none;
    display: flex; justify-content: space-between; align-items: center; gap: 16px;
}
summary::-webkit-details-marker { display: none; }
summary::after { content: "+"; color: var(--accent); font-size: 20px; line-height: 1; flex: none; }
details[open] summary::after { content: "\2212"; }
details > div { padding: 0 20px 18px; color: var(--text-muted); }

/* --- Footer -------------------------------------------------------------- */

.site-footer { background: var(--bg-sunken); border-top: 1px solid var(--border); padding: 48px 0 32px; font-size: 15px; }
.footer-grid { display: grid; gap: 28px; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

/* Once there is room, the four columns stop pretending to be equal. Site is the
   only one with six items in it and gets the width to run them two abreast;
   check-in holds one short line and gives that width up. Below this the
   auto-fit above still governs, which is what stacks them on a phone. */
@media (min-width: 900px) {
    .footer-grid { grid-template-columns: 1.7fr 1.1fr 1.1fr .7fr; }
}
/* Multi-column rather than a two-column grid: it balances the six links itself,
   so nothing breaks if a page is ever added or removed. */
.footer-site ul { columns: 2; column-gap: 26px; }
/* The column headings take the footer's own orange -- --foot-accent is the one already tuned
   for contrast on --bg-sunken in both themes (see its definition up top). */
.site-footer h4 { font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--foot-accent); margin: 0 0 12px; font-family: var(--font-mono); font-weight: 600; }
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: 7px; }
.site-footer a { color: var(--text); text-decoration: none; }
.site-footer a:hover { color: var(--brand); text-decoration: underline; }
/* The address column's map link is the one footer link that leaves the site, and it sits in a
   paragraph rather than a nav list -- so it takes the column heading's orange to read as a link
   at all, and its pin needs real space off the country name. */
.site-footer a.foot-map { color: var(--foot-accent); }
.site-footer a.foot-map:hover { color: var(--accent-dark); }
.foot-map-ico { vertical-align: -2px; margin-left: 7px; }
/* Both link columns -- Site and Contact -- behave like the header nav, so they
   get the header's treatment rather than a text colour and an underline: one
   height for every row, the chip's padding built into all of them rather than
   added to the selected one, and a hover that fills the row.

   .footer-grid, not .footer-site: the contact column is a list of links too.
   Only the two-column rule above stays site-only.

   The negative left margin cancels the left padding, so the chips grow outward
   and the link text stays lined up with the column heading above it. */
.footer-grid li { margin-bottom: 2px; }
.footer-grid li a {
    /* 44, not 32. Two of these rows are not one line -- the lockup is three and
       Viganj is two -- and at 32 the chip sat hard against them while the
       single-line rows kept their air. The tallest content is 34px, so this is
       what gives every row the same box and the same breathing room. */
    display: flex; align-items: center; min-height: 44px;
    /* max-content, or display:flex would stretch each link to the full column
       and the chip would read as a bar across it rather than around a word. */
    width: max-content; max-width: 100%;
    margin-left: -10px; padding: 0 10px;
    border-radius: var(--radius-sm);
}
/* The footer's own hover colour, not the header's --bg-alt -- that one is
   DARKER than this band in dark theme, so the hover would dig a hole in it. */
.footer-grid li a:hover {
    color: var(--text); background: var(--foot-hover-bg); text-decoration: none;
}
.site-footer a[aria-current="page"] { background: var(--foot-current-bg); }
/* Hovering the page you are already on must not repaint the marker in the
   hover colour -- the row would stop looking current for as long as the
   cursor sat on it. This is the more specific rule, so it holds the chip. */
.site-footer a[aria-current="page"]:hover {
    color: var(--text); text-decoration: none; background: var(--foot-current-bg);
}
.footer-bottom { margin-top: 34px; padding-top: 18px; border-top: 1px solid var(--border); color: var(--foot-accent); font-size: 14px; display: flex; flex-wrap: wrap; gap: 12px 24px; }

/* The copyright and the builder's credit stack as one block, so the credit sits UNDER the
   copyright rather than beside it -- the social row still takes the far end of the line.
   The credit is deliberately quieter than the line above it: it is the one thing in the
   footer that is not about Maestral, so it takes the muted text colour rather than the
   band's orange, and only the linked name gets the footer's link treatment. */
.foot-legal { display: flex; flex-direction: column; gap: 5px; }
.footer-bottom .credit { color: var(--text-muted); }
.site-footer .footer-bottom .credit a { color: var(--foot-accent); }
.site-footer .footer-bottom .credit a:hover { color: var(--accent-dark); text-decoration: underline; }

/* Social and listing links, pushed to the end of the bottom line so the legal
   text keeps the reading position. margin-left:auto only when there is room --
   once the row wraps on a phone they simply sit on their own line. */
.social { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.social a {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: var(--radius-sm);
    color: var(--foot-accent); text-decoration: none;
}
/* Hit target stays 34px; the mark itself is 18px, which is where these
   silhouettes still read. */
.social svg { width: 18px; height: 18px; }
/* Stays orange on hover -- the row is orange now, so swapping to the brand
   blue would read as a different control rather than the same one lit up.
   The fill does the work, and it is the footer's own hover colour: the
   header's --bg-alt is DARKER than this band in dark theme. */
.social a:hover { background: var(--foot-hover-bg); }

@media (max-width: 560px) {
    .social { margin-left: 0; }
}

/* --- Responsive ---------------------------------------------------------- */

/* The bar has to hold the brand, the menu and two icon buttons, and the menu's
   width is a translation, so this number is measured rather than chosen: the
   widest of the nine (German and Italian, tied) needs 246 + 16 + 569 + 96 + 48
   = 975px of viewport, and the narrowest (Croatian) 890. One breakpoint for all
   of them, set by the longest, because a per-language breakpoint is not a thing
   CSS can express. 1020 leaves 45px of margin, which is roughly one more word
   in one more language.

   The number moves whenever a row does: it was 1060 with three long single
   lines, 980 once FAQ and Viganj were stacked, and back up here now that Prices
   carries Reservation under it -- "Prenotazione" and "Reservierung" are longer
   than the words they sit beneath. Re-measure it rather than guessing. */
@media (max-width: 1020px) {
    .nav-toggle {
        display: inline-flex; align-items: center; justify-content: center;
        width: 38px; height: 38px; padding: 0; order: -1;
        background: transparent; border: 1px solid var(--border);
        border-radius: var(--radius-sm); color: var(--text); cursor: pointer;
    }
    .nav-toggle svg { width: 18px; height: 18px; }
    .site-nav {
        position: absolute; left: 0; right: 0; top: 100%;
        background: var(--bg); border-bottom: 1px solid var(--border);
        display: none; padding: 10px 24px 16px;
    }
    .site-nav[data-open="true"] { display: block; }
    .site-nav ul { flex-direction: column; gap: 2px; }
    .site-nav a { padding: 11px 12px; }
    .facts div { grid-template-columns: 1fr; gap: 4px; }
    .facts dt, .facts .k { padding-top: 0; }
}


/* --- Footer watermark -----------------------------------------------------
   Same idea as the AV mark on avento.hr: the logo set large and faint, bleeding
   past the top of the footer into the section above. .wrap inside the footer is
   position:relative so the columns paint over it without needing a z-index.
   ------------------------------------------------------------------------- */
.site-footer { position: relative; overflow: hidden; }
/* Sits fully inside the footer, not bled off the corner.
   The old right:-30px / bottom:-40px was tuned against the UNCROPPED artwork,
   whose empty margins absorbed most of the offset -- the drawing itself was
   barely clipped. Cropping those margins away meant the same offsets started
   cutting into the windsurfer and the vertical lettering instead. Zero on both
   edges, which is where the mark reads whole. */
/* Insets rather than flush to the corner: at right/bottom 0 the mark ran into
   the footer's own edge and, on a tall window, sat under the back-to-top button
   in the same corner. A little air reads as placed instead of cropped. */
.footer-mark {
    position: absolute; right: 26px; bottom: 28px;
    height: 260px; width: auto; opacity: .07;
    pointer-events: none; user-select: none;
}
.site-footer .wrap { position: relative; }
:root[data-theme="dark"] .footer-mark { opacity: .1; filter: brightness(1.8); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .footer-mark { opacity: .1; filter: brightness(1.8); }
}
@media (max-width: 720px) { .footer-mark { height: 170px; right: 16px; bottom: 18px; } }

/* --- Back to top ----------------------------------------------------------
   Appears after roughly one screen of scrolling, bottom right.

   Brand blue, NOT the accent. The accent is reserved for the primary call to
   action and the eyebrow rule -- a single warm note against a monochrome blue
   page is what makes a CTA findable, and spending it on a utility control would
   undo exactly that. avento.hr's button is orange because orange IS its brand.
   ------------------------------------------------------------------------- */
.to-top {
    position: fixed; right: 20px; bottom: 20px; z-index: 40;
    width: 44px; height: 44px; border-radius: var(--radius-sm);
    display: flex; align-items: center; justify-content: center;
    background: var(--brand); color: #fff;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .25);
    opacity: 0; visibility: hidden; transform: translateY(8px);
    transition: opacity .2s ease, transform .2s ease, visibility .2s ease,
                background-color .15s ease, box-shadow .15s ease;
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
/* Scoped to .is-visible so the hover lift cannot fight the transform that
   slides the button in. */
.to-top.is-visible:hover {
    background: var(--brand-dark);
    transform: translateY(-2px);
    box-shadow: 0 10px 26px rgba(0, 0, 0, .32);
}
.to-top svg { width: 20px; height: 20px; }

/* --- Contact form ---------------------------------------------------------
   Same markup, endpoint and honeypot as the avento.hr form. The field styling
   follows this site's tokens rather than being copied wholesale, so it inherits
   the blue focus ring instead of Avento's orange one.
   ------------------------------------------------------------------------- */
.contact-form { text-align: left; max-width: 640px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.field { margin: 0 0 16px; display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: .88rem; font-weight: 650; color: var(--text-muted); }
.field input, .field textarea {
    font: inherit; font-size: .98rem; color: var(--text);
    background: var(--bg);
    border: 1.5px solid var(--border);
    border-radius: var(--radius-sm);
    padding: .7rem .85rem;
    width: 100%;
    transition: border-color .15s ease, box-shadow .15s ease;
}
/* Smaller to start, and it grows with the text (see grow() in the js).
   overflow hidden so no scrollbar appears while it is still growing;
   the script turns it back on only past the height ceiling. */
.field textarea { resize: vertical; min-height: 92px; overflow-y: hidden; }
.field input:focus, .field textarea:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 25%, transparent);
}
/* Only mark a field red once the browser has actually judged it -- :invalid alone
   paints every required field red before the visitor has typed anything. */
.field input:user-invalid, .field textarea:user-invalid { border-color: #C0392B; }

/* Honeypot. Off-screen rather than display:none -- bots skip hidden inputs. */
.field-hp { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }

.form-actions { margin: 6px 0 0; }
.form-status { margin: 14px 0 0; font-size: .95rem; min-height: 1.4em; }
.form-status.is-ok { color: #1E8449; }
.form-status.is-error { color: #C0392B; }
:root[data-theme="dark"] .form-status.is-ok { color: #6FCF97; }
:root[data-theme="dark"] .form-status.is-error { color: #F1948A; }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .form-status.is-ok { color: #6FCF97; }
    :root:not([data-theme="light"]) .form-status.is-error { color: #F1948A; }
}
button[disabled] { opacity: .6; cursor: progress; }

@media (max-width: 560px) { .field-row { grid-template-columns: 1fr; } }


/* --- Photo slider ---------------------------------------------------------
   One image at a time, scrolled horizontally. The mechanism is the scroll
   container itself: scroll-snap does the paging, the controls just call
   scrollTo, and with JavaScript off or broken the track is still a scrollable
   strip you can drag, swipe or arrow through. Nothing here reimplements
   scrolling, which is why there is no transform, no index state and no
   transition to get out of step with the user's finger.

   scroll-behavior lives behind a no-preference query rather than being set and
   overridden: a slider is exactly the kind of lateral movement that makes
   motion-sensitive people ill, and reduced-motion should jump, not glide.
   ------------------------------------------------------------------------- */

.gallery-title { margin: 0 0 24px; }
.gallery-frame { position: relative; }

.slider-track {
    display: flex; gap: 16px;
    overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    /* The scrollbar is redundant next to arrows, dots and a snapping track, and
       on desktop it sat across the bottom of every photograph. */
    scrollbar-width: none; -ms-overflow-style: none;
}
.slider-track::-webkit-scrollbar { display: none; }
.slider-track:focus-visible { outline: 3px solid var(--brand); outline-offset: 3px; }
.slider-track img {
    flex: 0 0 100%; scroll-snap-align: center;
    display: block; width: 100%;
    /* A fixed box, because the set mixes 3:2 phone shots with 21:9 drone
       panoramas and a slider that changes height on every step is a fairground
       ride. object-fit crops to it; the aspect ratio also reserves the space,
       so lazy images do not shift the page as they arrive. */
    aspect-ratio: 16 / 10; object-fit: cover;
    border-radius: var(--radius); background: var(--bg-sunken);
}
@media (prefers-reduced-motion: no-preference) {
    .slider-track { scroll-behavior: smooth; }
}

/* The arrows sit ON the picture and appear on hover, which is where a visitor
   looks for them. Two things keep that from being a trap: they come back for
   :focus-within, so a keyboard never chases an invisible control, and on a
   touch device -- where there is no hover to reveal anything -- they are simply
   always there. */
.gallery-btn {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
    width: 40px; height: 40px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; border-radius: var(--radius-sm);
    background: rgba(9, 24, 38, .5); color: #fff;
    cursor: pointer;
    opacity: 0; transition: opacity .15s ease, background-color .15s ease;
}
.gallery-btn.prev { left: 10px; }
.gallery-btn.next { right: 10px; }
.gallery-frame:hover .gallery-btn,
.gallery-frame:focus-within .gallery-btn { opacity: 1; }
.gallery-btn:hover { background: rgba(9, 24, 38, .78); }
.gallery-btn[disabled] { opacity: 0 !important; }
.gallery-btn svg { width: 20px; height: 20px; }
@media (hover: none) {
    .gallery-btn { opacity: 1; }
    .gallery-btn[disabled] { opacity: .25 !important; }
}

.gallery-dots {
    display: flex; flex-wrap: wrap; justify-content: center;
    gap: 7px; margin-top: 16px;
}
.gallery-dot {
    width: 8px; height: 8px; padding: 0;
    border: 0; border-radius: 50%;
    background: var(--text-muted); opacity: .4;
    cursor: pointer;
    transition: opacity .15s ease, transform .15s ease;
}
.gallery-dot:hover { opacity: .7; }
.gallery-dot[aria-current] { background: var(--brand); opacity: 1; transform: scale(1.35); }
/* 8px is a small target for a finger. The hit area is grown with a pseudo
   element rather than padding, so the dots keep their spacing and their size. */
.gallery-dot::before {
    content: ""; position: absolute;
    width: 24px; height: 24px; margin: -8px 0 0 -8px;
}
.gallery-dot { position: relative; }

@media (prefers-reduced-motion: reduce) {
    .gallery-btn, .gallery-dot { transition: none; }
}

/* --- Map ------------------------------------------------------------------
   A Google Maps embed in an iframe. It replaced a self-hosted Leaflet map on
   OpenStreetMap tiles; the trade is deliberate and worth writing down, because
   the old code argued the other way in a comment that is now deleted.

   What it costs: the page now makes third-party requests to Google and the
   frame sets Google's cookies, which for an EU visitor is a consent question
   the rest of this site does not otherwise raise -- nothing else here loads
   from anyone but us and a cookieless analytics beacon. staticwebapp.config.json
   must allow the frame in frame-src or the CSP kills it silently.

   What it buys: the map people already know how to read, with the campsite's
   own Google listing and its reviews behind the pin.

   loading="lazy" keeps the frame off the critical path -- it sits far down the
   contact page and should not compete with anything above it. */
.map {
    display: block;
    height: 420px; width: 100%;
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--bg-alt);
}
@media (max-width: 620px) { .map { height: 320px; } }

/* Google's tiles are bright white; in dark mode they glare next to the page.
   Damped rather than inverted -- inverting makes the sea look like land. */
:root[data-theme="dark"] .map { filter: brightness(.82) saturate(.9); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .map { filter: brightness(.82) saturate(.9); }
}

/* --- aRento embeds (booking page) ----------------------------------------
   Two cross-origin iframes on the Map/Reservation page: the live aRento.Map
   WASM app and the menu-less booking embed. Both style like the Google map
   frame so the page reads as one thing.

   The live map wants real height -- it IS the page -- so it takes most of the
   viewport, floored so a landscape phone still gets something usable.

   The booking frame's height is set by js/maestral.js from the embed's own
   'pricing-height' postMessage, so the page never shows a second scrollbar;
   the value here is only the fallback until the first message arrives (and
   for the <noscript> copy, which cannot be measured). */
.live-map {
    display: block;
    width: 100%; height: clamp(440px, 74vh, 760px);
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--bg-alt);
}
.booking-frame {
    display: block;
    width: 100%; height: 1500px;
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--bg-alt);
}
.booking-frame[hidden] { display: none; }
.embed-note { margin-top: 10px; font-size: 14.5px; color: var(--text-muted); }

/* --- Live price list (contact page) ---------------------------------------
   Rows swapped in from aRento carry the item's icon before its name, the two
   held together by an inline-flex wrapper -- a bare img+text pair can wrap
   between the two whatever the white-space rules say. The icons are
   self-contained blue plates with the glyph baked in. */
#priceTable td .item-cell { display: inline-flex; align-items: center; gap: 8px; }
#priceTable td img.item-ico { width: 22px; height: 22px; border-radius: 5px; }
