/*
Theme Name: FlexFrame
Author: FlexFrame
Description: Lightweight WordPress block theme for performance-first Gutenberg/FSE websites.
Version: 2.1.5
Requires at least: 6.7
Tested up to: 7.1
Requires PHP: 8.1
Text Domain: flexframe
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Tags: block-theme, full-site-editing, block-patterns, wide-blocks, e-commerce, business, custom-colors, custom-logo, custom-menu, editor-style, featured-images, responsive-layout, translation-ready
*/

:root{--ff-header-z:1000}
html{scroll-behavior:smooth}
body{margin:0}
img{max-width:100%;height:auto}
.wp-site-blocks{min-height:100vh}
.ff-site-header{z-index:var(--ff-header-z)}
/* A stacking context for the menu, without taking the position the sticky
   support needs. This rule used to say position:relative outright, which won
   on load order and quietly turned a sticky header back into a static one. */
.ff-site-header:not(.is-position-sticky){position:relative}
/* A sticky element only sticks inside its parent's box, and this group's parent
   is the header element — exactly as tall as the header, so asking the group to
   stick pinned it for no distance at all. The wrapper does the sticking; the
   group keeps the editor control that asks for it, and hands over its own
   position so the two do not offset each other. Core's own offset variable
   keeps it clear of the admin bar. */
.wp-site-blocks > header.wp-block-template-part:has(> .ff-site-header.is-position-sticky){
  position:sticky;
  top:calc(0px + var(--wp-admin--admin-bar--position-offset, 0px));
  z-index:var(--ff-header-z);
}
.ff-site-header.is-position-sticky{position:static}
/* An in-page link lands under a pinned header unless the page is told to stop
   short of it. The header is 82px on a phone and a little less above that. */
html{scroll-padding-top:96px}
.ff-site-header .wp-block-button__link{transition:background-color .2s ease,color .2s ease,border-color .2s ease,transform .2s ease}
.ff-site-footer a{text-decoration:none}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

/* FlexFrame 1.4: lightweight header/footer defaults. */
.ff-site-header .wp-block-navigation__container{flex-wrap:nowrap}
.ff-site-header .wp-block-navigation-item__content{white-space:nowrap}
.ff-site-header .wp-block-buttons{flex-shrink:0}
.ff-site-header .wp-block-site-logo{flex-shrink:0}
.ff-site-footer ul{list-style:none;padding-left:0;margin:0}
.ff-site-footer li+li{margin-top:.38rem}
@media(max-width:1100px){.ff-site-header .wp-block-navigation__container{gap:.75rem}.ff-site-header .wp-block-navigation{font-size:.8rem}}

/* FlexFrame 1.8.5 — template shell continuity.
   Prevent theme block-gap from inserting whitespace between template parts and main. */
.wp-site-blocks > .wp-block-template-part + main,
.wp-site-blocks > header.wp-block-template-part + main,
.wp-site-blocks > main + .wp-block-template-part,
.wp-site-blocks > main + footer.wp-block-template-part{
  margin-block-start:0!important;
}

/* FlexFrame 2.2 — text colour inheritance inside coloured sections.
   theme.json gives core/paragraph its own colour, which WordPress emits as the
   element selector `p{color:…}`. An element selector beats inheritance, so a
   paragraph dropped into a group with a dark background kept the dark body
   colour and became unreadable — in a pattern, and equally for anyone building
   a section by hand. A parent that states its own colour should win. */
.has-text-color p:not([class*="-color"]),
.has-text-color li:not([class*="-color"]){
  color:inherit;
}

/* FlexFrame 2.3 — footer rhythm.
   The bottom row is a flex group, which on a narrow screen wraps into two
   left-aligned lines that read as a mistake rather than a layout. Centring both
   halves is what a person expects there. */
.ff-site-footer .ff-footer-bottom{
  gap:.75rem 1.5rem;
}
@media (max-width:781px){
  .ff-site-footer .ff-footer-bottom{
    justify-content:center;
    text-align:center;
  }
  /* The legal links are a flex row inside this one, and a flex row does not
     follow text-align — it has to be told to centre itself. */
  .ff-site-footer .ff-footer-bottom > *{
    flex:0 0 100%;
    text-align:center;
    display:flex;
    justify-content:center;
  }

  /* Core columns stack to one on a phone. The identity column reads well that
     way, but four link lists in a single stack is a very long scroll, so the
     menus sit two across and only the identity keeps the full width. */
  .ff-site-footer .wp-block-columns:not(.is-not-stacked-on-mobile){
    display:flex;
    flex-wrap:wrap;
    gap:2rem 1.5rem;
  }
  /* Core stacks columns on a phone with `flex-basis:100%!important`, so the
     override has to carry the same weight to be heard at all. */
  .ff-site-footer .wp-block-columns > .wp-block-column{
    flex-basis:calc(50% - .75rem)!important;
    flex-grow:0;
    min-width:0;
  }
  .ff-site-footer .wp-block-columns > .wp-block-column:first-child{
    flex-basis:100%!important;
  }
}

/* FlexFrame 2.4 — cards, links and the closing row.
   These are theme conventions, used by the theme's own patterns and by any site
   that keeps them. Nothing here names a client. */

/* A card lifts slightly under the pointer, which is the whole of the hover
   affordance — enough to say "this is one thing you can click". */
.ff-card{
  transition:transform .18s ease, box-shadow .18s ease;
}
@media (hover:hover){
  .ff-card:hover{
    transform:translateY(-4px);
    box-shadow:0 10px 28px rgba(19,36,51,.10);
  }
}
@media (prefers-reduced-motion:reduce){
  .ff-card{transition:none}
  .ff-card:hover{transform:none}
}

/* Underlines belong on links inside running text, where they distinguish a
   link from a word. A card title, a section link or a menu item is already
   obviously a control, and underlining every one of them makes a page look
   like a list of footnotes. */
.wp-site-blocks a:where(:not(.wp-element-button):not(.wp-block-navigation-item__content)){
  text-decoration:none;
}
/* A link answers the pointer with colour, not an underline. Underlining on
   hover also drew a second line under menu items, which already draw their own,
   and two underlines on one word is worse than none. */
.wp-site-blocks a:where(:not(.wp-element-button)):hover,
.wp-site-blocks a:where(:not(.wp-element-button)):focus-visible{
  color:var(--wp--preset--color--accent);
  text-decoration:none;
}

/* FlexFrame 2.5 — panels, badges, questions.

   A panel is a card that is not one of several: it takes the same frame and
   none of the hover, because there is nothing to click. */
.ff-panel{background:var(--wp--preset--color--white)}

/* An icon badge sits on the corner of a card picture. */
.ff-card__media{position:relative}
/* An icon badge is a round chip riding over the foot of a card picture. Its
   place, colour, shape and size are all block attributes, so the editor shows
   what the site shows; the only thing left to say is that it sits above the
   image rather than behind it. */
.ff-card__badge{position:relative;z-index:1}


/* Questions.
   A details element carries its own disclosure triangle, which cannot be
   styled; it is replaced with a plus that becomes a minus when open. Closed,
   each question is a quiet bar; open, it keeps the same frame and grows. */
.ff-faq details{
  border:1px solid var(--wp--preset--color--line);
  border-radius:8px;
  background:var(--wp--preset--color--surface);
  padding:14px 18px;
  transition:background .15s ease;
}
.ff-faq details[open]{background:var(--wp--preset--color--white)}
.ff-faq summary{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1rem;
  cursor:pointer;
  list-style:none;
  font-size:var(--wp--preset--font-size--sm);
  font-weight:500;
}
.ff-faq summary::-webkit-details-marker{display:none}
.ff-faq summary::after{
  content:"+";
  flex:0 0 auto;
  font-size:1.15rem;
  line-height:1;
  color:var(--wp--preset--color--primary);
}
.ff-faq details[open] summary::after{content:"−"}
.ff-faq details > :not(summary){
  margin-top:.75rem;
  font-size:var(--wp--preset--font-size--xs);
  color:var(--wp--preset--color--muted);
}

/* Full-width bands stack against each other.
   Block gap puts a margin between every top-level block, which is right for
   paragraphs and wrong for sections: it left a strip of the page background
   showing between one coloured band and the next, reading as a gap somebody
   forgot to close. */
.wp-block-post-content > .alignfull,
.wp-block-post-content > .alignfull + .alignfull{
  margin-block-start:0;
  margin-block-end:0;
}

/* Buttons.
   The ordinary hover is not here: theme.json already sets it through the
   button-hover-bg and button-hover-text presets, which is what the editor's own
   colour controls write to. A rule here duplicated that and, being more
   specific, beat it — so changing the hover colour in the editor did nothing.
   Only the two cases theme.json cannot express are stated, and both use
   :where() so they carry no specificity and anything set in the editor still
   wins. */
:where(.wp-element-button, .wp-block-button__link){
  transition:background-color .16s ease, color .16s ease, border-color .16s ease;
}
/* An outlined button fills rather than darkening; it has no background to
   darken. */
:where(.wp-block-button.is-style-outline > .wp-block-button__link:hover),
:where(.wp-block-button.is-style-outline > .wp-block-button__link:focus-visible){
  background-color:var(--wp--preset--color--button-bg);
  border-color:var(--wp--preset--color--button-bg);
  color:var(--wp--preset--color--button-text);
}
/* A white button sits on a dark band or a photograph, where the usual darker
   shade is invisible, so it inverts instead. */
:where(.wp-block-button > .wp-block-button__link.has-white-background-color:hover),
:where(.wp-block-button > .wp-block-button__link.has-white-background-color:focus-visible){
  background-color:var(--wp--preset--color--button-bg);
  color:var(--wp--preset--color--button-text);
}
@media (prefers-reduced-motion:reduce){
  :where(.wp-element-button, .wp-block-button__link){transition:none}
}

/* A closing card is a cover, so the picture already fills it at any size. The
   only thing to say is that its words sit at the foot, above the image rather
   than centred in it, which reads as a caption on a photograph. */
.ff-closing-card .wp-block-cover__inner-container{width:100%}
