/*
 * The Gelato frame - the moulding, the rabbet and the glazing.
 *
 * Shared by the builder (/create) and the home page hero, because they show
 * the same physical object and drifting apart is exactly how the hero came to
 * advertise a mat board the customer never receives. Linked by both
 * index.php and create/index.php; nothing else may restate these rules.
 *
 * Ported verbatim from /globes assets/create.css - The 1st Sale and Date of
 * Earth sell the same three Gelato mouldings, so diff the two before changing
 * either.
 */

:root {
  /* Anisotropic fractal grain, stretched along each rail. Wood is fractal, and
     evenly spaced gradient stripes are the giveaway of a fake frame. */
  --frame-grain-h: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='900' height='72'%3E%3Cfilter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.008 0.17' numOctaves='3' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1' result='n'/%3E%3CfeColorMatrix in='n' type='matrix' values='0 0 0 0 0.05 0 0 0 0 0.04 0 0 0 0 0.03 0.75 0 0 0 -0.375' result='d'/%3E%3CfeColorMatrix in='n' type='matrix' values='0 0 0 0 1 0 0 0 0 0.99 0 0 0 0 0.96 -0.66 0 0 0 0.33' result='l'/%3E%3CfeMerge%3E%3CfeMergeNode in='l'/%3E%3CfeMergeNode in='d'/%3E%3C/feMerge%3E%3C/filter%3E%3Crect width='900' height='72' filter='url(%23g)'/%3E%3C/svg%3E");
  --frame-grain-v: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='900'%3E%3Cfilter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.17 0.008' numOctaves='3' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1' result='n'/%3E%3CfeColorMatrix in='n' type='matrix' values='0 0 0 0 0.05 0 0 0 0 0.04 0 0 0 0 0.03 0.75 0 0 0 -0.375' result='d'/%3E%3CfeColorMatrix in='n' type='matrix' values='0 0 0 0 1 0 0 0 0 0.99 0 0 0 0 0.96 -0.66 0 0 0 0.33' result='l'/%3E%3CfeMerge%3E%3CfeMergeNode in='l'/%3E%3CfeMergeNode in='d'/%3E%3C/feMerge%3E%3C/filter%3E%3Crect width='72' height='900' filter='url(%23g)'/%3E%3C/svg%3E");
}

/*
 * The frame - ported verbatim from /globes (assets/create.css).
 *
 * This is the Date of Earth frame and it is deliberately not "simplified": the
 * earlier copy here rebuilt the grain out of evenly spaced gradient stripes and
 * dropped the glazing entirely, which is exactly the fake-frame giveaway the
 * note below warns about. Both products sell the same Gelato moulding, so the
 * two files must stay identical - diff them before changing either.
 */
/*
 * The frame.
 *
 * Modelled on the three mouldings Gelato actually ships: a flat-profile,
 * square-edged timber frame about 20mm across the face, in white-wrapped ash,
 * light natural oak and black ash. All three are shown straight on here, so the
 * face reads flat - the giveaway of a fake frame is a fat light-to-dark bevel
 * gradient across the rail, which these mouldings do not have.
 *
 * The grain is real anisotropic noise (feTurbulence stretched along the rail),
 * not stripes. Wood is fractal, and evenly spaced gradient lines are the other
 * giveaway. Each rail carries the texture lengthwise, so the four rails meet at
 * the mitre with the grain turning the corner exactly as milled stock does.
 * drawGelatoFrame() in create.js paints the same model onto canvas for the cart
 * and email snapshots.
 */
.frame-shell {
  position: relative;
  z-index: 1;
  width: 100%;
  height: auto;
  padding: 0;
  overflow: visible;
  transition: padding 0.2s ease, background 0.2s ease;
  /* Proportional, not clamped: the rail has to scale with the poster so the
     framed cart snapshot matches the builder at any viewport width. Resolves
     against .poster, the outer box the rail sits on. */
  --frame-rail: 4.8cqw;

  /* White-wrapped ash is the default; .frame-white restates it so the three
     colour classes read as one set. */
  --frame-face: #f4f3f0;
  --frame-face-lit: #fbfaf8;
  --frame-face-shade: #eae8e3;
  --frame-mute: rgba(244, 243, 240, 0.24);
  --frame-outer-edge: rgba(126, 121, 112, 0.42);
  --frame-outer-lip: rgba(255, 255, 255, 0.42);
  --frame-mitre: rgba(120, 114, 104, 0.24);
  --frame-rabbet: rgba(52, 47, 40, 0.34);
  --frame-rabbet-cast: rgba(38, 33, 27, 0.3);
  --frame-cast-shadow: rgba(15, 23, 42, 0.26);

}

.frame-rail {
  position: absolute;
  z-index: 1;
  display: none;
  pointer-events: none;
  /* Stretched, not tiled - see the texture note above. */
  background-size: 100% 100%;
  background-repeat: no-repeat;
  /* Bottom to top: face colour, grain, a wash of the face colour that dials the
     grain back to the contrast this particular wood has, then the edge lines.
     The streaks carry their own alpha, so no blend mode is involved - overlay
     and soft-light both collapse to nothing against a near-white face, which is
     exactly where the white moulding needs its texture to show. */
}

.frame-shell.framed > .frame-rail {
  display: block;
}

.frame-rail-top,
.frame-rail-bottom {
  left: 0;
  width: 100%;
  height: var(--frame-rail);
}

.frame-rail-left,
.frame-rail-right {
  top: 0;
  width: var(--frame-rail);
  height: 100%;
}

/*
 * Light falls from the top left, so the top and left rails carry the highlight
 * and the bottom and right rails sit a shade back. Across the face the shift is
 * deliberately small - a couple of percent - because a flat moulding catches
 * almost the same light edge to edge. The one firm line is at the inner edge,
 * where the face steps down into the rabbet.
 */
.frame-rail-top {
  top: 0;
  clip-path: polygon(0 0, 100% 0, calc(100% - var(--frame-rail)) 100%, var(--frame-rail) 100%);
  background-image:
    linear-gradient(180deg, var(--frame-outer-lip) 0, transparent 3%, transparent 88%, var(--frame-rabbet-cast) 100%),
    linear-gradient(var(--frame-mute), var(--frame-mute)),
    var(--frame-grain-h),
    linear-gradient(180deg, var(--frame-face-lit) 0%, var(--frame-face) 16%, var(--frame-face) 86%, var(--frame-face-shade) 100%);
}

.frame-rail-bottom {
  bottom: 0;
  clip-path: polygon(var(--frame-rail) 0, calc(100% - var(--frame-rail)) 0, 100% 100%, 0 100%);
  background-image:
    linear-gradient(0deg, var(--frame-outer-edge) 0, transparent 5%, transparent 88%, var(--frame-rabbet-cast) 100%),
    linear-gradient(var(--frame-mute), var(--frame-mute)),
    var(--frame-grain-h),
    linear-gradient(180deg, var(--frame-face-shade) 0%, var(--frame-face) 14%, var(--frame-face) 100%);
}

.frame-rail-left {
  left: 0;
  clip-path: polygon(0 0, 100% var(--frame-rail), 100% calc(100% - var(--frame-rail)), 0 100%);
  background-image:
    linear-gradient(90deg, var(--frame-outer-lip) 0, transparent 3%, transparent 88%, var(--frame-rabbet-cast) 100%),
    linear-gradient(var(--frame-mute), var(--frame-mute)),
    var(--frame-grain-v),
    linear-gradient(90deg, var(--frame-face-lit) 0%, var(--frame-face) 16%, var(--frame-face) 86%, var(--frame-face-shade) 100%);
}

.frame-rail-right {
  right: 0;
  clip-path: polygon(0 var(--frame-rail), 100% 0, 100% 100%, 0 calc(100% - var(--frame-rail)));
  background-image:
    linear-gradient(270deg, var(--frame-outer-edge) 0, transparent 5%, transparent 88%, var(--frame-rabbet-cast) 100%),
    linear-gradient(var(--frame-mute), var(--frame-mute)),
    var(--frame-grain-v),
    linear-gradient(90deg, var(--frame-face-shade) 0%, var(--frame-face) 14%, var(--frame-face) 100%);
}

.frame-shell.framed {
  padding: var(--frame-rail);
  background: var(--frame-face);
  /* A hung frame sits off the wall, so the shadow is offset down rather than
     spread evenly, and stays tight enough to read as a few cm of standoff. */
  box-shadow:
    0 22px 34px -12px var(--frame-cast-shadow),
    0 6px 12px -4px rgba(15, 23, 42, 0.16);
}

.frame-shell.framed::before,
.frame-shell.framed::after {
  content: "";
  position: absolute;
  pointer-events: none;
}

/*
 * The mitres and the outer edge of the moulding. The corner seams are four
 * hairlines running out of the corners at 45 degrees, where the rails' clip
 * paths already meet - without them the join between two differently lit rails
 * reads as a soft blur instead of a cut.
 */
.frame-shell.framed::before {
  z-index: 2;
  inset: 0;
  background:
    linear-gradient(135deg, var(--frame-mitre) 0 0.5px, transparent 0.5px) 0 0 / var(--frame-rail) var(--frame-rail) no-repeat,
    linear-gradient(225deg, var(--frame-mitre) 0 0.5px, transparent 0.5px) 100% 0 / var(--frame-rail) var(--frame-rail) no-repeat,
    linear-gradient(45deg, var(--frame-mitre) 0 0.5px, transparent 0.5px) 0 100% / var(--frame-rail) var(--frame-rail) no-repeat,
    linear-gradient(315deg, var(--frame-mitre) 0 0.5px, transparent 0.5px) 100% 100% / var(--frame-rail) var(--frame-rail) no-repeat;
  box-shadow: inset 0 0 0 1px var(--frame-outer-edge);
}

/* The wall shadow under the bottom edge, where a hung frame leans away. */
.frame-shell.framed::after {
  z-index: -1;
  inset: 14px 2px -12px 4px;
  background: var(--frame-cast-shadow);
  filter: blur(16px);
  opacity: 0.5;
}

/*
 * The print sits at the bottom of the rabbet, a few millimetres behind the
 * face, so the moulding casts a short shadow onto it from the top and left and
 * the rabbet edge itself reads as a hard line all the way round.
 */
.frame-shell.framed .poster-base {
  z-index: 3;
  box-shadow:
    0 0 0 1px var(--frame-rabbet),
    inset 4px 5px 9px -2px var(--frame-rabbet-cast);
}

/*
 * The glazing.
 *
 * A framed print is behind glass, and the one thing that reads as glass without
 * a photograph is the reflection of a window falling across it. It is a single
 * soft band with a weaker second pane trailing it, angled down to the right, and
 * it is kept low enough that the artwork underneath stays fully legible - this
 * sits over the customer's own design, so it can suggest glass but never
 * compete with it. Only ever drawn when framing is on: an unframed print ships
 * as a bare sheet, and canvas is never framed at all.
 *
 * drawGelatoGlass() in create.js repeats these three gradients on the canvas
 * snapshot, so the glass survives into the cart, the checkout summary, the
 * receipt and every email that shows the customer their design.
 */
.frame-shell.framed .poster-base::after {
  content: "";
  position: absolute;
  z-index: 6;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(128deg,
      rgba(255, 255, 255, 0) 19%,
      rgba(255, 255, 255, 0.125) 30%,
      rgba(255, 255, 255, 0.19) 37%,
      rgba(255, 255, 255, 0.088) 45%,
      rgba(255, 255, 255, 0) 56%),
    linear-gradient(128deg,
      rgba(255, 255, 255, 0) 59%,
      rgba(255, 255, 255, 0.072) 67%,
      rgba(255, 255, 255, 0) 76%),
    linear-gradient(158deg,
      rgba(255, 255, 255, 0.072) 0%,
      rgba(255, 255, 255, 0) 38%,
      rgba(10, 16, 30, 0.085) 100%);
}

/* Black ash. Open pores, so the grain runs at nearly full contrast - the
   texture is the only thing separating it from flat black. */
.frame-shell.framed.frame-black {
  --frame-face: #1b1a19;
  --frame-face-lit: #262422;
  --frame-face-shade: #131211;
  --frame-mute: rgba(27, 26, 25, 0.06);
  --frame-outer-edge: rgba(0, 0, 0, 0.68);
  --frame-outer-lip: rgba(255, 255, 255, 0.16);
  --frame-mitre: rgba(255, 255, 255, 0.13);
  --frame-rabbet: rgba(0, 0, 0, 0.72);
  --frame-rabbet-cast: rgba(0, 0, 0, 0.55);
  --frame-cast-shadow: rgba(12, 14, 20, 0.36);
}

/* White-wrapped ash. Painted, so the pores are filled and the grain shows as
   relief rather than colour - the lowest contrast of the three. */
.frame-shell.framed.frame-white {
  --frame-face: #f4f3f0;
  --frame-face-lit: #fbfaf8;
  --frame-face-shade: #eae8e3;
  --frame-mute: rgba(244, 243, 240, 0.24);
  --frame-outer-edge: rgba(126, 121, 112, 0.42);
  --frame-outer-lip: rgba(255, 255, 255, 0.42);
  --frame-mitre: rgba(120, 114, 104, 0.24);
  --frame-rabbet: rgba(52, 47, 40, 0.34);
  --frame-rabbet-cast: rgba(38, 33, 27, 0.3);
  --frame-cast-shadow: rgba(15, 23, 42, 0.26);
}

/* Light natural oak. Clear-finished, so the grain carries real colour, but the
   figure is fine and straight rather than the black's open pore. */
.frame-shell.framed.frame-timber {
  --frame-face: #cbb08c;
  --frame-face-lit: #d8c19f;
  --frame-face-shade: #bb9f79;
  --frame-mute: rgba(203, 176, 140, 0.3);
  --frame-outer-edge: rgba(96, 66, 34, 0.4);
  --frame-outer-lip: rgba(255, 242, 219, 0.3);
  --frame-mitre: rgba(94, 63, 31, 0.3);
  --frame-rabbet: rgba(74, 48, 22, 0.46);
  --frame-rabbet-cast: rgba(64, 41, 18, 0.4);
  --frame-cast-shadow: rgba(44, 32, 20, 0.28);
}
