/* ONETOO additions on top of the Webflow CSS. /css/* is cached immutable: bump the filename on edit. */

/* Plain .button links get the splash button's arrow reveal (markup added by scripts/fix_buttons.mjs). */
.button.has-arrow { display: inline-flex; align-items: center; justify-content: center; }
.button.has-arrow .arrow-wrapper { width: 0; height: 16px; margin-left: 0; display: flex; align-items: center; overflow: hidden; transition: .2s; }
.button.has-arrow svg.splash-arrow { width: 16px; height: 16px; flex: none; transform: translateX(-16px); transition: .2s; }
.button.has-arrow:hover .arrow-wrapper { width: 16px; margin-left: 6px; }
.button.has-arrow:hover svg.splash-arrow { transform: translateX(0); }
.button.has-arrow .button-text { white-space: nowrap; }
@media (prefers-reduced-motion: reduce) {
  .button.has-arrow .arrow-wrapper, .button.has-arrow svg.splash-arrow { transition: none; }
}

/* Inside a .black wrapper Webflow inverts buttons (.black .button: white on black) but also paints every
   descendant white (.black *), which turned the label and arrow that fix_buttons.mjs wraps in child divs
   white-on-white ("See more work" on every case study, "See the results" on /services and /approach). */
.black .button.has-arrow .button-text, .black .button.has-arrow .arrow-wrapper { color: inherit; }

/* WCAG AA: Webflow's #9b9b9b form hints ("[Optional]", "You'll hear from us…") are 2.8:1 on white at 13px. */
.label-span, .label.micro { color: #757575; }

/* Tabs (.tab-content): Webflow pads it 7.5px left/right at the mobile-portrait breakpoint only; not wanted. */
@media screen and (max-width: 479px) {
  .tab-content { padding-right: 0; padding-left: 0; }
}

/* Custom cursor dot: desktop only. The Webflow init swaps the hidden .adaptive-cursor class for
   has-*-state (no rule) and parks the dot at the last tap on touch devices (iOS synthesises
   mousemove), seen on the thank-you page 2026-10-12. Inline styles lose to !important. */
@media (hover: none), (pointer: coarse) {
  #adaptive-cursor { display: none !important; }
}

/* Accessibility batch 2026-10-12 (docs/ACCESSIBILITY-AUDIT-2026-10-12.md). The hamburger `.menu` is a
   <button> now (scripts/fix_a11y.mjs): drop the UA button chrome so the Webflow `.menu` rules render it
   exactly as the div did. No display/background here: `.menu` sets those per breakpoint. */
button.menu { padding: 0; border: 0; font: inherit; color: inherit; -webkit-appearance: none; appearance: none; cursor: pointer; }

/* 1.4.12 text spacing: `.nav-item` clips its text (overflow hidden, for the nav bubble); the brand pill
   has no bubble and lost 8px of "ONETOO.COM.AU" under the WCAG spacing override. */
.nav-brand.nav-item { overflow: visible; }


/* Type scale (2026-10-14): one small size and one body size. 13px becomes 13.33px (--type--0-833)
   and 18px becomes 20px (--type--paragraph). The 13px that rendered (services testimonials, article
   tables) came from page embeds, edited in live-pages/. The Webflow classes below matched no element
   on any page; set here so they cannot bring the old sizes back. Webflow's default h4 and
   blockquote 18px are already overridden to 20px by the site styles. */
.margin-0 p, .margin-0 li, .coming-soon { font-size: var(--type--0-833); }
.block-quote, .button.light, .text-style-quote { font-size: var(--type--paragraph); }

/* Tab lists and the /work filter on phones (Figma "Tab Flow", 2026-10-14). Under 480px Webflow
   scrolled the tab list inside the section's 15px padding (the last tab was cut off 15px short of
   the screen edge) and wrapped the work filter onto a second row. Both are now one row that scrolls
   sideways across the whole screen: negative margins equal to the section padding, the first item
   on the 15px content line, and 15px after the last (7.5px gap + 7.5px spacer). The width is set
   because the filter sits in a column flexbox that would otherwise size it to its content. The
   wrapping tab variant (.tab-wrap) is left as it is. */
@media screen and (max-width: 479px) {
  .filter-radio-group.tab-group:not(.tab-wrap),
  .work-group .filter-radio-wrapper {
    width: calc(100% + 2 * var(--spacing--small));
    margin-left: calc(-1 * var(--spacing--small));
    margin-right: calc(-1 * var(--spacing--small));
    padding-left: var(--spacing--small);
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-padding-inline: var(--spacing--small);
    scrollbar-width: none;
  }
  .filter-radio-group.tab-group:not(.tab-wrap)::-webkit-scrollbar,
  .work-group .filter-radio-wrapper::-webkit-scrollbar { display: none; }
  .filter-radio-group.tab-group:not(.tab-wrap)::after,
  .work-group .filter-radio-wrapper::after { content: ""; flex: none; width: var(--spacing--tiny); }
  /* Webflow makes every .filter-radio-group a scroller under 480px; around the filter it would
     clip the full-width row at its own 15px inset. The row scrolls, not the group. min-width: 0
     keeps the group (a grid item) from growing to the unwrapped row, which overflow did before. */
  .filter-radio-group.work-group { overflow: visible; min-width: 0; }
}

/* Mobile menu (Figma "Menu - Open" and "Menu - Close", 2026-10-14). */
@media screen and (max-width: 767px) {
  /* Hamburger: two 23px bars 3.75px apart (were 22.5px, 7.5px apart). IX2 still shows and hides the
     overlay, but its bar moves are fixed at 5px for the old gap and would cross the X off-centre.
     So the bars ignore IX2 (!important beats its inline transform) and follow aria-expanded, which
     /js/a11y-*.js keeps in step with the overlay. Same choreography as IX2: the bars meet, then
     rotate; on close they rotate back, then part. */
  .menu { row-gap: 3.75px; }
  .menu .h1, .menu .h3 { width: 23px; transform: none !important; transition: translate .2s ease-in .2s, rotate .2s ease-in; }
  .menu[aria-expanded="true"] .h1, .menu[aria-expanded="true"] .h3 { transition: translate .2s ease-in, rotate .2s ease-in .2s; }
  .menu[aria-expanded="true"] .h1 { translate: 0 3.375px; rotate: 45deg; }
  .menu[aria-expanded="true"] .h3 { translate: 0 -3.375px; rotate: -45deg; }

  /* Overlay: white (was 79% white over a 5px blur of the page), content on the 15px page margin,
     and the office clock and status (/js/clock-*.js) along the bottom. The white is the page's, faded
     to white underneath (see the end of this block), not the overlay's: a solid overlay fading in over
     a page fading out hid the page twice as fast on screen as behind Safari's bars. */
  .menu-wrap { background-color: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .menu-inner { padding: var(--spacing--small) var(--spacing--small) var(--spacing--regular); }
  .menu-link { letter-spacing: -.025em; }
  .menu-status { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--spacing--small); }
  .menu-status p { line-height: 1; }
  /* Dark pages (case studies, /services, /approach) wrap the whole page, nav included, in .black,
     whose page style paints every descendant white (`.black *`). On the old translucent overlay
     that read as white on light grey; on solid white it would vanish. Dark text on every page. */
  .menu-wrap .menu-inner * { color: var(--colour--black); }
  /* iOS 26 Safari ends the viewport at the top of its floating bottom toolbar, so the overlay
     (inset: 0) stopped there and the page showed under the toolbar. The overlay runs 200px past
     the bottom of the screen, padded back so the clock row stays where it was. */
  .menu-wrap { bottom: -200px; padding-bottom: 200px; }
  /* That did not reach behind the toolbar, nor behind the status bar (Marcel's iPhone, 2026-10-15),
     and neither did thin fixed strips on the screen edges: iOS 26 Safari shows the page itself
     there. So the page fades to white with the menu, and the whole screen changes as one, with
     IX2's own timing (action lists "a" and "a-5": 200ms inQuad, after the 200ms the bars take to
     meet on opening, at once on closing); hidden once faded. The state is the hamburger's
     aria-expanded, which /js/a11y-*.js sets as the overlay shows and clears on the closing tap. */
  main, footer { transition: opacity .2s cubic-bezier(.55, .085, .68, .53); }
  body > .black { transition: background-color .2s cubic-bezier(.55, .085, .68, .53); }
  body:has(button.menu[aria-expanded="true"]) :is(main, footer) { opacity: 0; visibility: hidden; transition: opacity .2s cubic-bezier(.55, .085, .68, .53) .2s, visibility 0s .4s; }
  body:has(button.menu[aria-expanded="true"]) > .black { background-color: #fff; transition: background-color .2s cubic-bezier(.55, .085, .68, .53) .2s; }
}
/* Behind Safari's status bar at the top of a page, and in the overscroll areas, Safari shows the
   document background: WebKit blends html's and body's, and an opaque body wins, so with body white
   on every page (Webflow) dark pages read white there even once html was black (Marcel's iPhone,
   2026-10-15, twice). Both take the page colour, and white while the menu is open, in step with the
   fade above. Nothing visible changes on the page: the .black wrapper covers body. */
html:has(body > .black), body:has(> .black) { background-color: var(--colour--black); transition: background-color .2s cubic-bezier(.55, .085, .68, .53); }
html:has(body > .black):has(button.menu[aria-expanded="true"]), body:has(> .black):has(button.menu[aria-expanded="true"]) { background-color: #fff; transition-delay: .2s; }
@media (prefers-reduced-motion: reduce) {
  .menu .h1, .menu .h3 { transition: none !important; }
}

/* Case studies (/work/<slug>): one template, scripts/case_study.mjs; content in content/work/
   (Figma "Once Again - ONETOO", desktop 3509:289, mobile 3513:108; 2026-10-14). The pages are dark
   (.black). Hero edge to edge under the floating nav (16:9, square on phones), then the title, the
   facts row, the gallery as before, the wrap-up and the next two projects. Facts text is the small
   size; labels are grey. */
.case-hero { position: relative; aspect-ratio: 16 / 9; margin-top: -60px; overflow: hidden; background-color: var(--colour--black); }
/* The hero is the video or image alone, square-cornered (gallery media are rounded). A video's poster
   is its first frame as an image underneath (fix_hero_posters.mjs), which shows until the video draws. */
.case-hero video, .case-hero img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 0; }
/* The video fades in on its first frame (autolablazyvideos sets data-playing): Safari paints a video
   that is still loading black, over the poster. Unplayed (reduced motion, Low Power Mode) it stays out. */
.case-hero video { opacity: 0; transition: opacity .3s; }
.case-hero video[data-playing] { opacity: 1; }
/* Gallery videos the same way: their frame as an image underneath, cropped like the video
   (fix_hero_posters.mjs), and the video fades in over it on its first frame. The image comes after
   the video in the markup, because each page's gallery CSS styles `.work-content :nth-child(n)` at
   any depth; the selector below outranks those rules and resets what they set. */
.content-video.has-poster { position: relative; }
.content-video.has-poster > video { position: relative; z-index: 1; opacity: 0; transition: opacity .3s; }
.content-video.has-poster > video[data-playing] { opacity: 1; }
.work-content .content-video.has-poster > img.video-poster { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; max-width: none; margin: 0; aspect-ratio: auto; object-fit: cover; border-radius: inherit; }
.section.case-head, .section.case-facts, .section.case-wrap, .section.case-next { margin-top: 0; margin-bottom: 0; }
/* 15px above and below the gallery, as in the frame (its own 7.5px margins collapse into these) */
.section.case-facts { margin-bottom: 15px; }
.section.case-wrap, .section.case-next { margin-top: 15px; }
.case-head .section-inner { padding: 30px 0 120px; }
.case-title { display: grid; grid-template-columns: 1fr 1fr; margin: 0; font-size: var(--type--heading); line-height: 1; letter-spacing: var(--letter-spacing--large); font-weight: 300; }
.black .case-title .case-intro { color: #b4b4b4; }
.case-facts-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--spacing--small); padding: 15px 0 60px; border-top: 1px solid var(--colour--white); }
.case-label, .case-value, .case-values, .case-essay p, .case-by { margin: 0; font-size: var(--type--0-833); line-height: 1.5; font-weight: 300; }
.case-values { padding: 0; list-style: none; }
.case-values li { margin: 0; font-size: inherit; line-height: inherit; list-style: none; }
.black .case-label, .black .case-by { color: #b4b4b4; }
.case-by { text-align: left; }
.case-values a, .case-value a { color: inherit; text-decoration: none; }
.case-values a:hover, .case-value a:hover { text-decoration: underline; }
.case-essay a { color: inherit; text-decoration: underline; }
.case-essay p + p { margin-top: 1.5em; }
.case-wrap-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--spacing--small); padding: 30px 0 60px; }
.case-info { grid-column: 1 / span 2; }
.case-aside { grid-column: 4; display: flex; flex-direction: column; gap: var(--spacing--large); }
.case-list { display: flex; flex-direction: column; gap: var(--spacing--small); }
.case-quote { margin: 0; }
.case-quote blockquote { padding: 0; border: 0; }
.case-next .section-inner { border-top: 1px solid var(--colour--white); }
.case-next-label { padding: 15px 0; }
.case-next-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--spacing--small); padding-bottom: 15px; }
@media screen and (max-width: 767px) {
  .case-hero { aspect-ratio: 1; }
  .case-head .section-inner { padding-bottom: 60px; }
  .case-title { display: block; font-size: var(--type--heading--mobile); }
  .case-title .case-client { display: block; }
  .case-facts-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 30px; }
  .case-wrap-grid { display: flex; flex-direction: column; row-gap: var(--spacing--large); }
  .case-next-grid { grid-template-columns: minmax(0, 1fr); }
}
