.frame-wrapper {
  --frame-aspect-ratio: 0.9;
  --frame-max-width: 500px;
  --frame-width: min(80vw, var(--frame-max-width), calc(80vh * var(--frame-aspect-ratio)));
  --frame-padding: 4px;
  --frame-handle-size: 2.5rem;

  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--frame-width);
  height: calc(var(--frame-width) / var(--frame-aspect-ratio));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  gap: calc(var(--frame-padding) * 2);
}

.frame-upper {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  border-radius: var(--border-radius);
  border: 1px solid;
  overflow: hidden;
  padding: var(--frame-padding);
}

.frame-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: var(--frame-padding);
  z-index: 2;
  background-color: var(--color-light-grey);
  border-radius: var(--border-radius-inner) var(--border-radius-inner) 0 0;
  border-width: 1px;
  border-style: solid solid none solid;
}

.frame-headline {
  display: none;
}
.frame-headline.is-active {
  display: block;
}

.frame-headline-right img {
  display: block;
  height: 2rem;
  width: auto;
}

.peaceful .frame-headline-right img {
  transform: scaleX(-1);
}

.frame-main {
  position: relative;
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
  overflow: hidden;
  border-radius: 0 0 var(--border-radius-inner) var(--border-radius-inner);
  border: 1px solid;
  background-color: var(--color-orange);
  padding: calc(var(--frame-width) * .2);
}

.peaceful .frame-main{
  background-color: transparent;
}

.frame-main img {
  grid-area: 1 / 1;
  min-width: 0;
  min-height: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  pointer-events: none;
}
.frame-main img.is-active {
  opacity: 1;
  pointer-events: auto;
}

.peaceful .frame-main img{
  visibility: hidden;
}

.frame-footer {
  position: relative;
  padding: var(--frame-padding);
  z-index: 2;
  border-radius: var(--border-radius);
  border: 1px solid;
  background-color: var(--color-light-grey);
}

/* The newsletter submit button doubles as the drag handle: it sits alone at the
   start of the collapsed form row, gets dragged across it, and settles into its
   own layout slot once the input expands beside it. */
.frame-footer .newsletter-submit-button {
  cursor: grab;
  touch-action: none;
}

.frame-footer .newsletter-submit-button.is-dragging {
  cursor: grabbing;
}

.frame-wrapper.dragging-finished .newsletter-submit-button {
  cursor: pointer;
  touch-action: auto;
}

/* Icons cross-fade while the reward spin is running. The transitions sit on the
   revealed state only: on the hidden state they would also animate whenever these
   rules first apply, flashing the icon and field on load before fading them out. */
.frame-footer .newsletter-submit-icon.is-handle {
  opacity: 1;
}

.frame-footer .newsletter-submit-icon.is-subscribe {
  opacity: 0;
}

.frame-wrapper.spinning .newsletter-submit-icon.is-handle {
  opacity: 0;
  transition: opacity 0.6s ease;
}

.frame-wrapper.spinning .newsletter-submit-icon.is-subscribe {
  opacity: 1;
  transition: opacity 0.6s ease;
}

/* The field keeps its width throughout so the handle's slot never moves, which is
   what lets the drag offset land at exactly 0 without anything to settle. */
.frame-footer .newsletter-form-field {
  opacity: 0;
  pointer-events: none;
}

.frame-wrapper.dragging-finished .newsletter-form-field {
  opacity: 1;
  pointer-events: auto;
  transition: opacity 0.5s ease;
}


.peace-button-wrapper{
  display: flex;
  position: absolute;
  left:var(--site-padding);
  top:50%;
  transform: translateY(-50%);
  cursor: pointer;
  gap: .5em;
  user-select: none;
}

.peace-button{
  background-color: var(--color-orange);
  width: 1em;
  height:1em;
  border-radius: 100%;
  box-shadow: var(--box-shadow-button);
}

.peaceful .peace-button{
  background-color: var(--color-dark-grey);
  box-shadow: var(--box-shadow-button-active);
  
}

/* visibility, not opacity or display: fading promotes the full-viewport canvas to its
   own compositing layer (which flashes the fixed frame on top of it), and display:none
   would collapse the body height it occupies. */
body:not(.peaceful) .particle-canvas {
  visibility: hidden;
}


/* The mode buttons lie on top of the newsletter form and take its place while the
   particles run, so the footer keeps the height the form gives it. Transitions sit
   on the revealed state only, same as the icons above. */
.mode-buttons {
  position: absolute;
  inset: var(--frame-padding);
  display: flex;
  align-items: center;
  gap: var(--frame-padding);
  opacity: 0;
  pointer-events: none;
}

body.peaceful .mode-buttons {
  opacity: 1;
  pointer-events: auto;
  transition: opacity 0.5s ease;
}

/* Same chip as the drag handle */
.mode-button {
  background: var(--color-dark-grey);
  border: none;
  width: var(--frame-handle-size);
  height: var(--frame-handle-size);
  box-sizing: border-box;
  padding: var(--padding-buttons);
  border-radius: var(--border-radius-inner);
  cursor: pointer;
  transition: background 0.3s ease;
  user-select: none;
  box-shadow: var(--box-shadow-button);
  display: block;
}

[data-mode="1"] .mode-button:nth-of-type(2),
[data-mode="0"] .mode-button:nth-of-type(1){
  background-color: var(--color-orange);
  box-shadow: var(--box-shadow-button-active);
}

.mode-button img {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Cut, not faded: the form's own parts (field, icons) carry transitions of their
   own, so fading the wrapper plays them all over again on every toggle. */
body.peaceful .frame-footer .newsletter-form-wrapper {
  opacity: 0;
  pointer-events: none;
}
